/*
 * Microsoft JDBC Driver for SQL Server Copyright(c) Microsoft Corporation All rights reserved. This program is made
 * available under the terms of the MIT License. See the LICENSE file in the project root for more information.
 */
package com.microsoft.sqlserver.jdbc.datatypes;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.fail;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.IOException;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

import com.microsoft.sqlserver.jdbc.Geography;
import com.microsoft.sqlserver.jdbc.Geometry;
import com.microsoft.sqlserver.jdbc.RandomUtil;
import com.microsoft.sqlserver.jdbc.SQLServerException;
import com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement;
import com.microsoft.sqlserver.jdbc.SQLServerResultSet;
import com.microsoft.sqlserver.jdbc.TestResource;
import com.microsoft.sqlserver.jdbc.TestUtils;
import com.microsoft.sqlserver.testframework.AbstractSQLGenerator;
import com.microsoft.sqlserver.testframework.AbstractTest;
import com.microsoft.sqlserver.testframework.Constants;


/**
 * Test Geometry / Geography classes
 *
 */
@RunWith(JUnitPlatform.class)
public class SQLServerSpatialDatatypeTest extends AbstractTest {

    static String geomTableName;
    static String geogTableName;
    static String spatialDatatypeTableName;
    static boolean isDenaliOrLater = false;

    /**
     * Tests basic point scenario.
     */
    @Test
    public void testPoint() throws SQLException {
        String geoWKT = "POINT(3 40 5 6)";
        byte[] geomCLR = hexStringToByteArray(
                "00000000010F0000000000000840000000000000444000000000000014400000000000001840");
        byte[] geogCLR = hexStringToByteArray(
                "E6100000010F0000000000004440000000000000084000000000000014400000000000001840");
        byte[] geoWKB = hexStringToByteArray("010100000000000000000008400000000000004440");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests empty point scenario.
     */
    @Test
    public void testPointEmpty() throws SQLException {
        String geoWKT = "POINT EMPTY";
        byte[] geomCLR = hexStringToByteArray("407100000104000000000000000001000000FFFFFFFFFFFFFFFF01");
        byte[] geogCLR = hexStringToByteArray("E61000000104000000000000000001000000FFFFFFFFFFFFFFFF01");
        byte[] geoWKB = hexStringToByteArray("010400000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests basic linestring scenario.
     */
    @Test
    public void testLineString() throws SQLException {
        String geoWKT = "LINESTRING(1 0, 0 1, -1 0)";
        byte[] geomCLR = hexStringToByteArray(
                "00000000010403000000000000000000F03F00000000000000000000000000000000000000000000F03F000000000000F0BF000000000000000001000000010000000001000000FFFFFFFF0000000002");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000104030000000000000000000000000000000000F03F000000000000F03F00000000000000000000000000000000000000000000F0BF01000000010000000001000000FFFFFFFF0000000002");
        byte[] geoWKB = hexStringToByteArray(
                "010200000003000000000000000000F03F00000000000000000000000000000000000000000000F03F000000000000F0BF0000000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests empty linestring scenario.
     */
    @Test
    public void testLineStringEmpty() throws SQLException {
        String geoWKT = "LINESTRING EMPTY";
        byte[] geomCLR = hexStringToByteArray("FFFF00000104000000000000000001000000FFFFFFFFFFFFFFFF02");
        byte[] geogCLR = hexStringToByteArray("E61000000104000000000000000001000000FFFFFFFFFFFFFFFF02");
        byte[] geoWKB = hexStringToByteArray("010200000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests basic polygon scenario.
     */
    @Test
    public void testPolygon() throws SQLException {
        String geoWKT = "POLYGON((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1))";
        byte[] geomCLR = hexStringToByteArray(
                "000000000104090000000000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F020000000200000000000500000001000000FFFFFFFF0000000003");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000200090000000000000000000000000000000000000000000000000008400000000000000000000000000000084000000000000008400000000000000000000000000000084000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F020000000100000000010500000001000000FFFFFFFF0000000003");
        byte[] geoWKB = hexStringToByteArray(
                "01030000000200000005000000000000000000000000000000000000000000000000000000000000000000084000000000000008400000000000000840000000000000084000000000000000000000000000000000000000000000000004000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests empty polygon scenario.
     */
    @Test
    public void testPolygonEmpty() throws SQLException {
        String geoWKT = "POLYGON EMPTY";
        byte[] geomCLR = hexStringToByteArray("FFFF00000104000000000000000001000000FFFFFFFFFFFFFFFF03");
        byte[] geogCLR = hexStringToByteArray("E61000000104000000000000000001000000FFFFFFFFFFFFFFFF03");
        byte[] geoWKB = hexStringToByteArray("010300000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests basic multipoint scenario.
     */
    @Test
    public void testMultiPoint() throws SQLException {
        String geoWKT = "MULTIPOINT((2 3), (7 8 9.5))";
        byte[] geomCLR = hexStringToByteArray(
                "00000000010502000000000000000000004000000000000008400000000000001C400000000000002040000000000000F8FF0000000000002340020000000100000000010100000003000000FFFFFFFF0000000004000000000000000001000000000100000001");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000105020000000000000000000840000000000000004000000000000020400000000000001C40000000000000F8FF0000000000002340020000000100000000010100000003000000FFFFFFFF0000000004000000000000000001000000000100000001");
        byte[] geoWKB = hexStringToByteArray(
                "01040000000200000001010000000000000000000040000000000000084001010000000000000000001C400000000000002040");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests empty multipoint scenario.
     */
    @Test
    public void testMultiPointEmpty() throws SQLException {
        String geoWKT = "MULTIPOINT EMPTY";
        byte[] geomCLR = hexStringToByteArray("FFFF00000104000000000000000001000000FFFFFFFFFFFFFFFF04");
        byte[] geogCLR = hexStringToByteArray("E61000000104000000000000000001000000FFFFFFFFFFFFFFFF04");
        byte[] geoWKB = hexStringToByteArray("010400000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests basic multilinestring scenario.
     */
    @Test
    public void testMultiLineString() throws SQLException {
        String geoWKT = "MULTILINESTRING((0 2, 1 1), (1 0, 1 1))";
        byte[] geomCLR = hexStringToByteArray(
                "0000000001040400000000000000000000000000000000000040000000000000F03F000000000000F03F000000000000F03F0000000000000000000000000000F03F000000000000F03F020000000100000000010200000003000000FFFFFFFF0000000005000000000000000002000000000100000002");
        byte[] geogCLR = hexStringToByteArray(
                "E610000001040400000000000000000000400000000000000000000000000000F03F000000000000F03F0000000000000000000000000000F03F000000000000F03F000000000000F03F020000000100000000010200000003000000FFFFFFFF0000000005000000000000000002000000000100000002");
        byte[] geoWKB = hexStringToByteArray(
                "01050000000200000001020000000200000000000000000000000000000000000040000000000000F03F000000000000F03F010200000002000000000000000000F03F0000000000000000000000000000F03F000000000000F03F");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests empty multilinestring scenario.
     */
    @Test
    public void testMultiLineStringEmpty() throws SQLException {
        String geoWKT = "MULTILINESTRING EMPTY";
        byte[] geomCLR = hexStringToByteArray("FFFF00000104000000000000000001000000FFFFFFFFFFFFFFFF05");
        byte[] geogCLR = hexStringToByteArray("E61000000104000000000000000001000000FFFFFFFFFFFFFFFF05");
        byte[] geoWKB = hexStringToByteArray("010500000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests basic multipolygon scenario.
     */
    @Test
    public void testMultiPolygon() throws SQLException {
        String geoWKT = "MULTIPOLYGON(((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)))";
        byte[] geomCLR = hexStringToByteArray(
                "0000000001010D000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F000000000000000000000000000000000000000000000000000000000000084000000000000008400000000000000840000000000000084000000000000000000000000000000000000000000000000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001C40000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0300000002000000000004000000020900000003000000FFFFFFFF0000000006000000000000000003000000000200000003");
        byte[] geogCLR = hexStringToByteArray(
                "E610000002010D000000000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F000000000000000000000000000000000000000000000840000000000000000000000000000008400000000000000840000000000000000000000000000008400000000000000000000000000000000000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001C40000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0300000001000000000104000000010900000003000000FFFFFFFF0000000006000000000000000003000000000200000003");
        byte[] geoWKB = hexStringToByteArray(
                "01060000000200000001030000000200000004000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F0500000000000000000000000000000000000000000000000000000000000000000008400000000000000840000000000000084000000000000008400000000000000000000000000000000000000000000000000103000000010000000400000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests basic multipolygon scenario.
     */
    @Test
    public void testMultiPolygon2() throws SQLException {
        String geoWKT = "MULTIPOLYGON(((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)))";
        byte[] geomCLR = hexStringToByteArray(
                "0000000001010D00000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F0000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001C400300000002000000000204000000000800000003000000FFFFFFFF0000000006000000000000000003000000000100000003");
        byte[] geogCLR = hexStringToByteArray(
                "E610000002010D00000000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000000000000000000000000000000000008400000000000000000000000000000084000000000000008400000000000000000000000000000084000000000000000000000000000000000000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001C400300000001000000000104000000010800000003000000FFFFFFFF0000000006000000000000000003000000000100000003");
        byte[] geoWKB = hexStringToByteArray(
                "010600000002000000010300000001000000040000000000000000002240000000000000224000000000000022400000000000002440000000000000244000000000000022400000000000002240000000000000224001030000000200000004000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F050000000000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests basic multipolygon scenario.
     */
    @Test
    public void testMultiPolygon3() throws SQLException {
        String geoWKT = "MULTIPOLYGON(((9 9, 9 10, 10 9, 9 9), (12 12, 0 0, 12 12, 12 12), (1 0, 3 4, 4 5, 6 7, 1 0)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)))";
        byte[] geomCLR = hexStringToByteArray(
                "0000000001011A0000000000000000002240000000000000224000000000000022400000000000002440000000000000244000000000000022400000000000002240000000000000224000000000000028400000000000002840000000000000000000000000000000000000000000002840000000000000284000000000000028400000000000002840000000000000F03F0000000000000000000000000000084000000000000010400000000000001040000000000000144000000000000018400000000000001C40000000000000F03F000000000000000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F0000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001C4006000000020000000000040000000008000000020D0000000211000000001500000004000000FFFFFFFF0000000006000000000000000003000000000300000003000000000400000003");
        byte[] geogCLR = hexStringToByteArray(
                "E610000002011A00000000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000284000000000000028400000000000000000000000000000000000000000000028400000000000002840000000000000284000000000000028400000000000000000000000000000F03F00000000000010400000000000000840000000000000144000000000000010400000000000001C4000000000000018400000000000000000000000000000F03F00000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000000000000000000000000000000000008400000000000000000000000000000084000000000000008400000000000000000000000000000084000000000000000000000000000000000000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001C4006000000010000000001040000000108000000010D0000000111000000011500000004000000FFFFFFFF0000000006000000000000000003000000000300000003000000000400000003");
        byte[] geoWKB = hexStringToByteArray(
                "0106000000030000000103000000030000000400000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240040000000000000000002840000000000000284000000000000000000000000000000000000000000000284000000000000028400000000000002840000000000000284005000000000000000000F03F0000000000000000000000000000084000000000000010400000000000001040000000000000144000000000000018400000000000001C40000000000000F03F0000000000000000010300000001000000040000000000000000002240000000000000224000000000000022400000000000002440000000000000244000000000000022400000000000002240000000000000224001030000000200000004000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F050000000000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests basic multipolygon scenario.
     */
    @Test
    public void testMultiPolygon4() throws SQLException {
        String geoWKT = "MULTIPOLYGON(((9 9, 9 10, 10 9, 9 9)))";
        byte[] geomCLR = hexStringToByteArray(
                "000000000104040000000000000000002240000000000000224000000000000022400000000000002440000000000000244000000000000022400000000000002240000000000000224001000000020000000002000000FFFFFFFF0000000006000000000000000003");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000224040000000000000000002240000000000000224000000000000024400000000000002240000000000000224000000000000024400000000000002240000000000000224001000000010000000002000000FFFFFFFF0000000006000000000000000003");
        byte[] geoWKB = hexStringToByteArray(
                "0106000000010000000103000000010000000400000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests empty multipolygon scenario.
     */
    @Test
    public void testMultiPolygonEmpty() throws SQLException {
        String geoWKT = "MULTIPOLYGON EMPTY";
        byte[] geomCLR = hexStringToByteArray("000000000104000000000000000001000000FFFFFFFFFFFFFFFF06");
        byte[] geogCLR = hexStringToByteArray("E61000000104000000000000000001000000FFFFFFFFFFFFFFFF06");
        byte[] geoWKB = hexStringToByteArray("010600000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(POINT(3 3 1), LINESTRING(1 0, 0 1, -1 0), CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3), POLYGON((0 0 2, 1 10 3, 1 0 4, 0 0 2), (0 0 2, 1 10 3, 1 0 4, 0 0 2), (0 0 2, 1 10 3, 1 0 4, 0 0 2)), MULTIPOINT((2 3), (7 8 9.5)), MULTILINESTRING((0 2, 1 1), (1 0, 1 1)), MULTIPOLYGON(((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1)), ((9 9, 9 10, 10 9, 9 9))), COMPOUNDCURVE(CIRCULARSTRING(1 0 3, 0 1 3, 9 6 3, 8 7 3, -1 0 3), CIRCULARSTRING(-1 0 3, 7 9 3, -10 2 3), (-10 2 3, 77 77 77, 88 88 88, 2 6 4), (2 6 4, 3 3 6, 7 7 1)), CURVEPOLYGON((0 0, 0 0, 0 0, 0 0), COMPOUNDCURVE((0 -23.43778, 0 23.43778), CIRCULARSTRING(0 23.43778, -45 -23.43778, 0 -23.43778)), COMPOUNDCURVE((0 -23.43778, 7 7, 0 23.43778), CIRCULARSTRING(0 23.43778, 8 8, 8 8, -45 23.43778, -90 23.43778), (-90 23.43778, -90 -23.43778), CIRCULARSTRING(-90 -23.43778, -45 -23.43778, 0 -23.43778))), POLYGON((0 0 2, 1 10 3, 1 0 4, 0 0 2)))";
        byte[] geomCLR = hexStringToByteArray(
                "0100000002014A00000000000000000008400000000000000840000000000000F03F00000000000000000000000000000000000000000000F03F000000000000F0BF0000000000000000000000000000F03F00000000000008400000000000000840000000000000144000000000000010400000000000001C400000000000001C400000000000000840000000000000F03F000000000000084000000000000000000000000000000000000000000000F03F0000000000002440000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F0000000000002440000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F0000000000002440000000000000F03F000000000000000000000000000000000000000000000000000000000000004000000000000008400000000000001C40000000000000204000000000000000000000000000000040000000000000F03F000000000000F03F000000000000F03F0000000000000000000000000000F03F000000000000F03F0000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F00000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240000000000000F03F00000000000000000000000000000000000000000000F03F0000000000002240000000000000184000000000000020400000000000001C40000000000000F0BF00000000000000000000000000001C40000000000000224000000000000024C00000000000000040000000000040534000000000004053400000000000005640000000000000564000000000000000400000000000001840000000000000084000000000000008400000000000001C400000000000001C40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C7D79E59127037C00000000000000000C7D79E591270374000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C00000000000000000C7D79E59127037C00000000000001C400000000000001C400000000000000000C7D79E5912703740000000000000204000000000000020400000000000002040000000000000204000000000008046C0C7D79E591270374000000000008056C0C7D79E591270374000000000008056C0C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C000000000000000000000000000000000000000000000F03F0000000000002440000000000000F03F000000000000000000000000000000000000000000000000000000000000F03F000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000004000000000000008400000000000001040000000000000004000000000000000400000000000000840000000000000104000000000000000400000000000000040000000000000084000000000000010400000000000000040000000000000F8FF0000000000002340000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF00000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000405340000000000000564000000000000010400000000000001840000000000000F03F000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000000040000000000000084000000000000010400000000000000040120000000100000000010100000002040000000109000000010D00000001110000000115000000011600000001170000000119000000011B00000001200000000124000000032800000001340000000338000000033C000000014600000011000000FFFFFFFF0000000007000000000000000001000000000100000002000000000200000008000000000300000003000000000600000004050000000600000001050000000700000001000000000800000005080000000800000002080000000900000002000000000A000000060B0000000A000000030B0000000C00000003000000000D00000009000000000E0000000A0000000011000000031000000003010302000002000203020003010203");
        byte[] geogCLR = hexStringToByteArray(
                "E610000002214A000000000000000000084000000000000008400000000000000000000000000000F03F000000000000F03F00000000000000000000000000000000000000000000F0BF0000000000000840000000000000F03F000000000000144000000000000008400000000000001C40000000000000104000000000000008400000000000001C400000000000000840000000000000F03F000000000000000000000000000000000000000000002440000000000000F03F0000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000002440000000000000F03F0000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000002440000000000000F03F0000000000000000000000000000F03F000000000000000000000000000000000000000000000840000000000000004000000000000020400000000000001C4000000000000000400000000000000000000000000000F03F000000000000F03F0000000000000000000000000000F03F000000000000F03F000000000000F03F0000000000000000000000000000000000000000000008400000000000000000000000000000084000000000000008400000000000000000000000000000084000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F000000000000224000000000000022400000000000002440000000000000224000000000000022400000000000002440000000000000224000000000000022400000000000000000000000000000F03F000000000000F03F0000000000000000000000000000184000000000000022400000000000001C4000000000000020400000000000000000000000000000F0BF00000000000022400000000000001C40000000000000004000000000000024C0000000000040534000000000004053400000000000005640000000000000564000000000000018400000000000000040000000000000084000000000000008400000000000001C400000000000001C4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C7D79E59127037C00000000000000000C7D79E59127037400000000000000000C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C000000000000000000000000000001C400000000000001C40C7D79E591270374000000000000000000000000000002040000000000000204000000000000020400000000000002040C7D79E591270374000000000008046C0C7D79E591270374000000000008056C0C7D79E59127037C000000000008056C0C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000000000000000000000000000000000000000000000002440000000000000F03F0000000000000000000000000000F03F00000000000000000000000000000000000000000000F03F000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000004000000000000008400000000000001040000000000000004000000000000000400000000000000840000000000000104000000000000000400000000000000040000000000000084000000000000010400000000000000040000000000000F8FF0000000000002340000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF00000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000405340000000000000564000000000000010400000000000001840000000000000F03F000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000000040000000000000084000000000000010400000000000000040120000000100000000010100000002040000000109000000010D00000001110000000115000000011600000001170000000119000000011B00000001200000000124000000032800000001340000000338000000033C000000014600000011000000FFFFFFFF0000000007000000000000000001000000000100000002000000000200000008000000000300000003000000000600000004050000000600000001050000000700000001000000000800000005080000000800000002080000000900000002000000000A000000060B0000000A000000030B0000000C00000003000000000D00000009000000000E0000000A0000000011000000031000000003010302000002000203020003010203");
        byte[] geoWKB = hexStringToByteArray(
                "01070000000A000000010100000000000000000008400000000000000840010200000003000000000000000000F03F00000000000000000000000000000000000000000000F03F000000000000F0BF0000000000000000010800000005000000000000000000F03F00000000000008400000000000000840000000000000144000000000000010400000000000001C400000000000001C400000000000000840000000000000F03F00000000000008400103000000030000000400000000000000000000000000000000000000000000000000F03F0000000000002440000000000000F03F0000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000F03F0000000000002440000000000000F03F0000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000F03F0000000000002440000000000000F03F00000000000000000000000000000000000000000000000001040000000200000001010000000000000000000040000000000000084001010000000000000000001C40000000000000204001050000000200000001020000000200000000000000000000000000000000000040000000000000F03F000000000000F03F010200000002000000000000000000F03F0000000000000000000000000000F03F000000000000F03F01060000000200000001030000000200000005000000000000000000000000000000000000000000000000000000000000000000084000000000000008400000000000000840000000000000084000000000000000000000000000000000000000000000000004000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F0103000000010000000400000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240010900000004000000010800000005000000000000000000F03F00000000000000000000000000000000000000000000F03F0000000000002240000000000000184000000000000020400000000000001C40000000000000F0BF0000000000000000010800000003000000000000000000F0BF00000000000000000000000000001C40000000000000224000000000000024C0000000000000004001020000000400000000000000000024C0000000000000004000000000004053400000000000405340000000000000564000000000000056400000000000000040000000000000184001020000000300000000000000000000400000000000001840000000000000084000000000000008400000000000001C400000000000001C40010A00000003000000010200000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000109000000020000000102000000020000000000000000000000C7D79E59127037C00000000000000000C7D79E59127037400108000000030000000000000000000000C7D79E591270374000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C00109000000040000000102000000030000000000000000000000C7D79E59127037C00000000000001C400000000000001C400000000000000000C7D79E59127037400108000000050000000000000000000000C7D79E5912703740000000000000204000000000000020400000000000002040000000000000204000000000008046C0C7D79E591270374000000000008056C0C7D79E591270374001020000000200000000000000008056C0C7D79E591270374000000000008056C0C7D79E59127037C001080000000300000000000000008056C0C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C00103000000010000000400000000000000000000000000000000000000000000000000F03F0000000000002440000000000000F03F000000000000000000000000000000000000000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests empty geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection1() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION EMPTY";
        byte[] geomCLR = hexStringToByteArray("100000000104000000000000000001000000FFFFFFFFFFFFFFFF07");
        byte[] geogCLR = hexStringToByteArray("E61000000104000000000000000001000000FFFFFFFFFFFFFFFF07");
        byte[] geoWKB = hexStringToByteArray("010700000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests empty geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection2() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY)";
        byte[] geomCLR = hexStringToByteArray(
                "100000000104000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF07");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000104000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF07");
        byte[] geoWKB = hexStringToByteArray("010700000001000000010700000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection3() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(POINT(3 40 5 6))";
        byte[] geomCLR = hexStringToByteArray(
                "10000000010701000000000000000000084000000000000044400000000000001440000000000000184001000000010000000002000000FFFFFFFF0000000007000000000000000001");
        byte[] geogCLR = hexStringToByteArray(
                "E6100000010701000000000000000000444000000000000008400000000000001440000000000000184001000000010000000002000000FFFFFFFF0000000007000000000000000001");
        byte[] geoWKB = hexStringToByteArray("010700000001000000010100000000000000000008400000000000004440");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection4() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(POINT EMPTY)";
        byte[] geomCLR = hexStringToByteArray(
                "100000000104000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF01");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000104000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF01");
        byte[] geoWKB = hexStringToByteArray("010700000001000000010400000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection5() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(LINESTRING(1 0, 0 1, -1 0))";
        byte[] geomCLR = hexStringToByteArray(
                "10000000010403000000000000000000F03F00000000000000000000000000000000000000000000F03F000000000000F0BF000000000000000001000000010000000002000000FFFFFFFF0000000007000000000000000002");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000104030000000000000000000000000000000000F03F000000000000F03F00000000000000000000000000000000000000000000F0BF01000000010000000002000000FFFFFFFF0000000007000000000000000002");
        byte[] geoWKB = hexStringToByteArray(
                "010700000001000000010200000003000000000000000000F03F00000000000000000000000000000000000000000000F03F000000000000F0BF0000000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection6() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(LINESTRING EMPTY)";
        byte[] geomCLR = hexStringToByteArray(
                "100000000104000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF02");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000104000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF02");
        byte[] geoWKB = hexStringToByteArray("010700000001000000010200000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection7() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(POLYGON((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1)))";
        byte[] geomCLR = hexStringToByteArray(
                "100000000104090000000000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F020000000200000000000500000002000000FFFFFFFF0000000007000000000000000003");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000200090000000000000000000000000000000000000000000000000008400000000000000000000000000000084000000000000008400000000000000000000000000000084000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F020000000100000000010500000002000000FFFFFFFF0000000007000000000000000003");
        byte[] geoWKB = hexStringToByteArray(
                "01070000000100000001030000000200000005000000000000000000000000000000000000000000000000000000000000000000084000000000000008400000000000000840000000000000084000000000000000000000000000000000000000000000000004000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection8() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(POLYGON EMPTY)";
        byte[] geomCLR = hexStringToByteArray(
                "100000000104000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF03");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000104000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF03");
        byte[] geoWKB = hexStringToByteArray("010700000001000000010300000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection9() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(MULTIPOINT((2 3), (7 8 9.5)))";
        byte[] geomCLR = hexStringToByteArray(
                "10000000010502000000000000000000004000000000000008400000000000001C400000000000002040000000000000F8FF0000000000002340020000000100000000010100000004000000FFFFFFFF0000000007000000000000000004010000000000000001010000000100000001");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000105020000000000000000000840000000000000004000000000000020400000000000001C40000000000000F8FF0000000000002340020000000100000000010100000004000000FFFFFFFF0000000007000000000000000004010000000000000001010000000100000001");
        byte[] geoWKB = hexStringToByteArray(
                "01070000000100000001040000000200000001010000000000000000000040000000000000084001010000000000000000001C400000000000002040");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection10() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(MULTIPOINT EMPTY)";
        byte[] geomCLR = hexStringToByteArray(
                "100000000104000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF04");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000104000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF04");
        byte[] geoWKB = hexStringToByteArray("010700000001000000010400000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection11() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(MULTILINESTRING((0 2, 1 1), (1 0, 1 1)))";
        byte[] geomCLR = hexStringToByteArray(
                "1000000001040400000000000000000000000000000000000040000000000000F03F000000000000F03F000000000000F03F0000000000000000000000000000F03F000000000000F03F020000000100000000010200000004000000FFFFFFFF0000000007000000000000000005010000000000000002010000000100000002");
        byte[] geogCLR = hexStringToByteArray(
                "E610000001040400000000000000000000400000000000000000000000000000F03F000000000000F03F0000000000000000000000000000F03F000000000000F03F000000000000F03F020000000100000000010200000004000000FFFFFFFF0000000007000000000000000005010000000000000002010000000100000002");
        byte[] geoWKB = hexStringToByteArray(
                "01070000000100000001050000000200000001020000000200000000000000000000000000000000000040000000000000F03F000000000000F03F010200000002000000000000000000F03F0000000000000000000000000000F03F000000000000F03F");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection12() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(MULTILINESTRING EMPTY)";
        byte[] geomCLR = hexStringToByteArray(
                "100000000104000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF05");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000104000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF05");
        byte[] geoWKB = hexStringToByteArray("010700000001000000010500000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection13() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(MULTIPOLYGON(((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9))))";
        byte[] geomCLR = hexStringToByteArray(
                "1000000001010D000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F000000000000000000000000000000000000000000000000000000000000084000000000000008400000000000000840000000000000084000000000000000000000000000000000000000000000000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001C40000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0300000002000000000004000000020900000004000000FFFFFFFF0000000007000000000000000006010000000000000003010000000200000003");
        byte[] geogCLR = hexStringToByteArray(
                "E610000002010D000000000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F000000000000000000000000000000000000000000000840000000000000000000000000000008400000000000000840000000000000000000000000000008400000000000000000000000000000000000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001C40000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0300000001000000000104000000010900000004000000FFFFFFFF0000000007000000000000000006010000000000000003010000000200000003");
        byte[] geoWKB = hexStringToByteArray(
                "01070000000100000001060000000200000001030000000200000004000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F0500000000000000000000000000000000000000000000000000000000000000000008400000000000000840000000000000084000000000000008400000000000000000000000000000000000000000000000000103000000010000000400000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection14() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(MULTIPOLYGON(((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7))))";
        byte[] geomCLR = hexStringToByteArray(
                "1000000001010D00000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F0000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001C400300000002000000000204000000000800000004000000FFFFFFFF0000000007000000000000000006010000000000000003010000000100000003");
        byte[] geogCLR = hexStringToByteArray(
                "E610000002010D00000000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000000000000000000000000000000000008400000000000000000000000000000084000000000000008400000000000000000000000000000084000000000000000000000000000000000000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001C400300000001000000000104000000010800000004000000FFFFFFFF0000000007000000000000000006010000000000000003010000000100000003");
        byte[] geoWKB = hexStringToByteArray(
                "010700000001000000010600000002000000010300000001000000040000000000000000002240000000000000224000000000000022400000000000002440000000000000244000000000000022400000000000002240000000000000224001030000000200000004000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F050000000000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection15() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(MULTIPOLYGON(((9 9, 9 10, 10 9, 9 9), (12 12, 0 0, 12 12, 12 12), (1 0, 3 4, 4 5, 6 7, 1 0)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7))))";
        byte[] geomCLR = hexStringToByteArray(
                "1000000001011A0000000000000000002240000000000000224000000000000022400000000000002440000000000000244000000000000022400000000000002240000000000000224000000000000028400000000000002840000000000000000000000000000000000000000000002840000000000000284000000000000028400000000000002840000000000000F03F0000000000000000000000000000084000000000000010400000000000001040000000000000144000000000000018400000000000001C40000000000000F03F000000000000000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F0000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001C4006000000020000000000040000000008000000020D0000000211000000001500000005000000FFFFFFFF0000000007000000000000000006010000000000000003010000000300000003010000000400000003");
        byte[] geogCLR = hexStringToByteArray(
                "E610000002011A00000000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000284000000000000028400000000000000000000000000000000000000000000028400000000000002840000000000000284000000000000028400000000000000000000000000000F03F00000000000010400000000000000840000000000000144000000000000010400000000000001C4000000000000018400000000000000000000000000000F03F00000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000000000000000000000000000000000008400000000000000000000000000000084000000000000008400000000000000000000000000000084000000000000000000000000000000000000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001C4006000000010000000001040000000108000000010D0000000111000000011500000005000000FFFFFFFF0000000007000000000000000006010000000000000003010000000300000003010000000400000003");
        byte[] geoWKB = hexStringToByteArray(
                "0107000000010000000106000000030000000103000000030000000400000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240040000000000000000002840000000000000284000000000000000000000000000000000000000000000284000000000000028400000000000002840000000000000284005000000000000000000F03F0000000000000000000000000000084000000000000010400000000000001040000000000000144000000000000018400000000000001C40000000000000F03F0000000000000000010300000001000000040000000000000000002240000000000000224000000000000022400000000000002440000000000000244000000000000022400000000000002240000000000000224001030000000200000004000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F050000000000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection16() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(MULTIPOLYGON(((9 9, 9 10, 10 9, 9 9))))";
        byte[] geomCLR = hexStringToByteArray(
                "100000000104040000000000000000002240000000000000224000000000000022400000000000002440000000000000244000000000000022400000000000002240000000000000224001000000020000000003000000FFFFFFFF0000000007000000000000000006010000000000000003");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000224040000000000000000002240000000000000224000000000000024400000000000002240000000000000224000000000000024400000000000002240000000000000224001000000010000000003000000FFFFFFFF0000000007000000000000000006010000000000000003");
        byte[] geoWKB = hexStringToByteArray(
                "0107000000010000000106000000010000000103000000010000000400000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection17() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(MULTIPOLYGON EMPTY)";
        byte[] geomCLR = hexStringToByteArray(
                "100000000104000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF06");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000104000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF06");
        byte[] geoWKB = hexStringToByteArray("010700000001000000010600000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection18() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(CIRCULARSTRING(2 1 3 4, 1 2 3, 0 7 3, 1 0 3, 2 1 3))";
        byte[] geomCLR = hexStringToByteArray(
                "100000000207050000000000000000000040000000000000F03F000000000000F03F000000000000004000000000000000000000000000001C40000000000000F03F00000000000000000000000000000040000000000000F03F000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000001040000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF01000000020000000002000000FFFFFFFF0000000007000000000000000008");
        byte[] geogCLR = hexStringToByteArray(
                "E6100000020705000000000000000000F03F00000000000000400000000000000040000000000000F03F0000000000001C4000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000001040000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF01000000020000000002000000FFFFFFFF0000000007000000000000000008");
        byte[] geoWKB = hexStringToByteArray(
                "0107000000010000000108000000050000000000000000000040000000000000F03F000000000000F03F000000000000004000000000000000000000000000001C40000000000000F03F00000000000000000000000000000040000000000000F03F");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection19() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(CIRCULARSTRING EMPTY)";
        byte[] geomCLR = hexStringToByteArray(
                "100000000204000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF08");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000204000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF08");
        byte[] geoWKB = hexStringToByteArray("010700000001000000010800000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection20() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(COMPOUNDCURVE(CIRCULARSTRING(1 0 3, 0 1 3, 9 6 3, 8 7 3, -1 0 3), CIRCULARSTRING(-1 0 3, 7 9 3, -10 2 3), (-10 2 3, 77 77 77, 88 88 88, 2 6 4), (2 6 4, 3 3 6, 7 7 1)))";
        byte[] geomCLR = hexStringToByteArray(
                "1000000002050C000000000000000000F03F00000000000000000000000000000000000000000000F03F0000000000002240000000000000184000000000000020400000000000001C40000000000000F0BF00000000000000000000000000001C40000000000000224000000000000024C00000000000000040000000000040534000000000004053400000000000005640000000000000564000000000000000400000000000001840000000000000084000000000000008400000000000001C400000000000001C4000000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000405340000000000000564000000000000010400000000000001840000000000000F03F01000000030000000002000000FFFFFFFF0000000007000000000000000009080000000301030200000200");
        byte[] geogCLR = hexStringToByteArray(
                "E610000002050C0000000000000000000000000000000000F03F000000000000F03F0000000000000000000000000000184000000000000022400000000000001C4000000000000020400000000000000000000000000000F0BF00000000000022400000000000001C40000000000000004000000000000024C0000000000040534000000000004053400000000000005640000000000000564000000000000018400000000000000040000000000000084000000000000008400000000000001C400000000000001C4000000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000405340000000000000564000000000000010400000000000001840000000000000F03F01000000030000000002000000FFFFFFFF0000000007000000000000000009080000000301030200000200");
        byte[] geoWKB = hexStringToByteArray(
                "010700000001000000010900000004000000010800000005000000000000000000F03F00000000000000000000000000000000000000000000F03F0000000000002240000000000000184000000000000020400000000000001C40000000000000F0BF0000000000000000010800000003000000000000000000F0BF00000000000000000000000000001C40000000000000224000000000000024C0000000000000004001020000000400000000000000000024C0000000000000004000000000004053400000000000405340000000000000564000000000000056400000000000000040000000000000184001020000000300000000000000000000400000000000001840000000000000084000000000000008400000000000001C400000000000001C40");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection21() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(COMPOUNDCURVE(CIRCULARSTRING(-1 0 3, 7 9 3, -10 2 3), (-10 2 3, 77 77 3, 88 88 3, 2 6 3), (2 6 3, 3 3 3, 2 6 3), CIRCULARSTRING(2 6 3, 0 1 3, 2 6 3)))";
        byte[] geomCLR = hexStringToByteArray(
                "1000000002010A000000000000000000F0BF00000000000000000000000000001C40000000000000224000000000000024C0000000000000004000000000004053400000000000405340000000000000564000000000000056400000000000000040000000000000184000000000000008400000000000000840000000000000004000000000000018400000000000000000000000000000F03F00000000000000400000000000001840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084001000000030000000002000000FFFFFFFF00000000070000000000000000090700000003020000020003");
        byte[] geogCLR = hexStringToByteArray(
                "E610000002010A0000000000000000000000000000000000F0BF00000000000022400000000000001C40000000000000004000000000000024C00000000000405340000000000040534000000000000056400000000000005640000000000000184000000000000000400000000000000840000000000000084000000000000018400000000000000040000000000000F03F000000000000000000000000000018400000000000000040000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084001000000030000000002000000FFFFFFFF00000000070000000000000000090700000003020000020003");
        byte[] geoWKB = hexStringToByteArray(
                "010700000001000000010900000004000000010800000003000000000000000000F0BF00000000000000000000000000001C40000000000000224000000000000024C0000000000000004001020000000400000000000000000024C00000000000000040000000000040534000000000004053400000000000005640000000000000564000000000000000400000000000001840010200000003000000000000000000004000000000000018400000000000000840000000000000084000000000000000400000000000001840010800000003000000000000000000004000000000000018400000000000000000000000000000F03F00000000000000400000000000001840");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection22() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(COMPOUNDCURVE((1 1, 1 1)))";
        byte[] geomCLR = hexStringToByteArray(
                "10000000020002000000000000000000F03F000000000000F03F000000000000F03F000000000000F03F01000000030000000002000000FFFFFFFF00000000070000000000000000090100000002");
        byte[] geogCLR = hexStringToByteArray(
                "E6100000020002000000000000000000F03F000000000000F03F000000000000F03F000000000000F03F01000000030000000002000000FFFFFFFF00000000070000000000000000090100000002");
        byte[] geoWKB = hexStringToByteArray(
                "010700000001000000010900000001000000010200000002000000000000000000F03F000000000000F03F000000000000F03F000000000000F03F");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection23() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(COMPOUNDCURVE EMPTY)";
        byte[] geomCLR = hexStringToByteArray(
                "100000000204000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF09");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000204000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF09");
        byte[] geoWKB = hexStringToByteArray("010700000001000000010900000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection24() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(CURVEPOLYGON((0 0, 0 0, 0 0, 0 0), CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3), COMPOUNDCURVE((0 -23.43778, 0 23.43778), CIRCULARSTRING(0 23.43778, -45 -23.43778, 0 -23.43778)), COMPOUNDCURVE((0 -23.43778, 7 7, 0 23.43778), CIRCULARSTRING(0 23.43778, 8 8, 8 8, -45 23.43778, -90 23.43778), (-90 23.43778, -90 -23.43778), CIRCULARSTRING(-90 -23.43778, -45 -23.43778, 0 -23.43778))))";
        byte[] geomCLR = hexStringToByteArray(
                "1000000002001700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F00000000000008400000000000000840000000000000144000000000000010400000000000001C400000000000001C400000000000000840000000000000F03F00000000000008400000000000000000C7D79E59127037C00000000000000000C7D79E591270374000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C00000000000000000C7D79E59127037C00000000000001C400000000000001C400000000000000000C7D79E5912703740000000000000204000000000000020400000000000002040000000000000204000000000008046C0C7D79E591270374000000000008056C0C7D79E591270374000000000008056C0C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C004000000010000000002040000000309000000030D00000002000000FFFFFFFF000000000700000000000000000A080000000203020003010203");
        byte[] geogCLR = hexStringToByteArray(
                "E6100000020017000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000840000000000000F03F000000000000144000000000000008400000000000001C40000000000000104000000000000008400000000000001C400000000000000840000000000000F03FC7D79E59127037C00000000000000000C7D79E59127037400000000000000000C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C000000000000000000000000000001C400000000000001C40C7D79E591270374000000000000000000000000000002040000000000000204000000000000020400000000000002040C7D79E591270374000000000008046C0C7D79E591270374000000000008056C0C7D79E59127037C000000000008056C0C7D79E59127037C000000000008046C0C7D79E59127037C0000000000000000004000000010000000002040000000309000000030D00000002000000FFFFFFFF000000000700000000000000000A080000000203020003010203");
        byte[] geoWKB = hexStringToByteArray(
                "010700000001000000010A0000000400000001020000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010800000005000000000000000000F03F00000000000008400000000000000840000000000000144000000000000010400000000000001C400000000000001C400000000000000840000000000000F03F00000000000008400109000000020000000102000000020000000000000000000000C7D79E59127037C00000000000000000C7D79E59127037400108000000030000000000000000000000C7D79E591270374000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C00109000000040000000102000000030000000000000000000000C7D79E59127037C00000000000001C400000000000001C400000000000000000C7D79E59127037400108000000050000000000000000000000C7D79E5912703740000000000000204000000000000020400000000000002040000000000000204000000000008046C0C7D79E591270374000000000008056C0C7D79E591270374001020000000200000000000000008056C0C7D79E591270374000000000008056C0C7D79E59127037C001080000000300000000000000008056C0C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C0");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection25() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(CURVEPOLYGON((0 0, 0 0, 0 0, 0 0)))";
        byte[] geomCLR = hexStringToByteArray(
                "100000000200040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000002000000FFFFFFFF000000000700000000000000000A");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000200040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000002000000FFFFFFFF000000000700000000000000000A");
        byte[] geoWKB = hexStringToByteArray(
                "010700000001000000010A0000000100000001020000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection26() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(CURVEPOLYGON(CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3)))";
        byte[] geomCLR = hexStringToByteArray(
                "10000000020405000000000000000000F03F00000000000008400000000000000840000000000000144000000000000010400000000000001C400000000000001C400000000000000840000000000000F03F000000000000084001000000020000000002000000FFFFFFFF000000000700000000000000000A");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000224050000000000000000000840000000000000F03F000000000000144000000000000008400000000000001C40000000000000104000000000000008400000000000001C400000000000000840000000000000F03F01000000020000000002000000FFFFFFFF000000000700000000000000000A");
        byte[] geoWKB = hexStringToByteArray(
                "010700000001000000010A00000001000000010800000005000000000000000000F03F00000000000008400000000000000840000000000000144000000000000010400000000000001C400000000000001C400000000000000840000000000000F03F0000000000000840");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection27() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(COMPOUNDCURVE((0 -23.43778, 0 23.43778)))";
        byte[] geomCLR = hexStringToByteArray(
                "100000000204020000000000000000000000C7D79E59127037C00000000000000000C7D79E591270374001000000030000000002000000FFFFFFFF00000000070000000000000000090100000002");
        byte[] geogCLR = hexStringToByteArray(
                "E6100000020402000000C7D79E59127037C00000000000000000C7D79E5912703740000000000000000001000000030000000002000000FFFFFFFF00000000070000000000000000090100000002");
        byte[] geoWKB = hexStringToByteArray(
                "0107000000010000000109000000010000000102000000020000000000000000000000C7D79E59127037C00000000000000000C7D79E5912703740");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection28() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(COMPOUNDCURVE EMPTY)";
        byte[] geomCLR = hexStringToByteArray(
                "100000000204000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF09");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000204000000000000000002000000FFFFFFFFFFFFFFFF0700000000FFFFFFFF09");
        byte[] geoWKB = hexStringToByteArray("010700000001000000010900000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection29() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(3 3 1), LINESTRING(1 0, 0 1, -1 0), CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3), POLYGON((0 0 2, 1 10 3, 1 0 4, 0 0 2), (0 0 2, 1 10 3, 1 0 4, 0 0 2), (0 0 2, 1 10 3, 1 0 4, 0 0 2)), MULTIPOINT((2 3), (7 8 9.5)), MULTILINESTRING((0 2, 1 1), (1 0, 1 1)), MULTIPOLYGON(((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1)), ((9 9, 9 10, 10 9, 9 9))), COMPOUNDCURVE(CIRCULARSTRING(1 0 3, 0 1 3, 9 6 3, 8 7 3, -1 0 3), CIRCULARSTRING(-1 0 3, 7 9 3, -10 2 3), (-10 2 3, 77 77 77, 88 88 88, 2 6 4), (2 6 4, 3 3 6, 7 7 1)), CURVEPOLYGON((0 0, 0 0, 0 0, 0 0), COMPOUNDCURVE((0 -23.43778, 0 23.43778), CIRCULARSTRING(0 23.43778, -45 -23.43778, 0 -23.43778)), COMPOUNDCURVE((0 -23.43778, 7 7, 0 23.43778), CIRCULARSTRING(0 23.43778, 8 8, 8 8, -45 23.43778, -90 23.43778), (-90 23.43778, -90 -23.43778), CIRCULARSTRING(-90 -23.43778, -45 -23.43778, 0 -23.43778))), POLYGON((0 0 2, 1 10 3, 1 0 4, 0 0 2))), GEOMETRYCOLLECTION EMPTY, CURVEPOLYGON((0 0, 0 0, 0 0, 0 0), CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3), COMPOUNDCURVE((0 -23.43778, 0 23.43778), CIRCULARSTRING(0 23.43778, -45 -23.43778, 0 -23.43778)), COMPOUNDCURVE((0 -23.43778, 7 7, 0 23.43778), CIRCULARSTRING(0 23.43778, 8 8, 8 8, -45 23.43778, -90 23.43778), (-90 23.43778, -90 -23.43778), CIRCULARSTRING(-90 -23.43778, -45 -23.43778, 0 -23.43778))))";
        byte[] geomCLR = hexStringToByteArray(
                "1000000002016100000000000000000008400000000000000840000000000000F03F00000000000000000000000000000000000000000000F03F000000000000F0BF0000000000000000000000000000F03F00000000000008400000000000000840000000000000144000000000000010400000000000001C400000000000001C400000000000000840000000000000F03F000000000000084000000000000000000000000000000000000000000000F03F0000000000002440000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F0000000000002440000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F0000000000002440000000000000F03F000000000000000000000000000000000000000000000000000000000000004000000000000008400000000000001C40000000000000204000000000000000000000000000000040000000000000F03F000000000000F03F000000000000F03F0000000000000000000000000000F03F000000000000F03F0000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F00000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240000000000000F03F00000000000000000000000000000000000000000000F03F0000000000002240000000000000184000000000000020400000000000001C40000000000000F0BF00000000000000000000000000001C40000000000000224000000000000024C00000000000000040000000000040534000000000004053400000000000005640000000000000564000000000000000400000000000001840000000000000084000000000000008400000000000001C400000000000001C40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C7D79E59127037C00000000000000000C7D79E591270374000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C00000000000000000C7D79E59127037C00000000000001C400000000000001C400000000000000000C7D79E5912703740000000000000204000000000000020400000000000002040000000000000204000000000008046C0C7D79E591270374000000000008056C0C7D79E591270374000000000008056C0C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C000000000000000000000000000000000000000000000F03F0000000000002440000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F00000000000008400000000000000840000000000000144000000000000010400000000000001C400000000000001C400000000000000840000000000000F03F00000000000008400000000000000000C7D79E59127037C00000000000000000C7D79E591270374000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C00000000000000000C7D79E59127037C00000000000001C400000000000001C400000000000000000C7D79E5912703740000000000000204000000000000020400000000000002040000000000000204000000000008046C0C7D79E591270374000000000008056C0C7D79E591270374000000000008056C0C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C0000000000000F03F000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000004000000000000008400000000000001040000000000000004000000000000000400000000000000840000000000000104000000000000000400000000000000040000000000000084000000000000010400000000000000040000000000000F8FF0000000000002340000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF00000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000405340000000000000564000000000000010400000000000001840000000000000F03F000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000000040000000000000084000000000000010400000000000000040000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF160000000100000000010100000002040000000109000000010D00000001110000000115000000011600000001170000000119000000011B00000001200000000124000000032800000001340000000338000000033C0000000146000000014A000000024E0000000353000000035700000014000000FFFFFFFF0000000007000000000000000007010000000000000001010000000100000002010000000200000008010000000300000003010000000600000004060000000600000001060000000700000001010000000800000005090000000800000002090000000900000002010000000A000000060C0000000A000000030C0000000C00000003010000000D00000009010000000E0000000A01000000110000000300000000FFFFFFFF0700000000120000000A18000000030103020000020002030200030102030203020003010203");
        byte[] geogCLR = hexStringToByteArray(
                "E6100000020161000000000000000000084000000000000008400000000000000000000000000000F03F000000000000F03F00000000000000000000000000000000000000000000F0BF0000000000000840000000000000F03F000000000000144000000000000008400000000000001C40000000000000104000000000000008400000000000001C400000000000000840000000000000F03F000000000000000000000000000000000000000000002440000000000000F03F0000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000002440000000000000F03F0000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000002440000000000000F03F0000000000000000000000000000F03F000000000000000000000000000000000000000000000840000000000000004000000000000020400000000000001C4000000000000000400000000000000000000000000000F03F000000000000F03F0000000000000000000000000000F03F000000000000F03F000000000000F03F0000000000000000000000000000000000000000000008400000000000000000000000000000084000000000000008400000000000000000000000000000084000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F000000000000224000000000000022400000000000002440000000000000224000000000000022400000000000002440000000000000224000000000000022400000000000000000000000000000F03F000000000000F03F0000000000000000000000000000184000000000000022400000000000001C4000000000000020400000000000000000000000000000F0BF00000000000022400000000000001C40000000000000004000000000000024C0000000000040534000000000004053400000000000005640000000000000564000000000000018400000000000000040000000000000084000000000000008400000000000001C400000000000001C4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C7D79E59127037C00000000000000000C7D79E59127037400000000000000000C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C000000000000000000000000000001C400000000000001C40C7D79E591270374000000000000000000000000000002040000000000000204000000000000020400000000000002040C7D79E591270374000000000008046C0C7D79E591270374000000000008056C0C7D79E59127037C000000000008056C0C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000000000000000000000000000000000000000000000002440000000000000F03F0000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000840000000000000F03F000000000000144000000000000008400000000000001C40000000000000104000000000000008400000000000001C400000000000000840000000000000F03FC7D79E59127037C00000000000000000C7D79E59127037400000000000000000C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C000000000000000000000000000001C400000000000001C40C7D79E591270374000000000000000000000000000002040000000000000204000000000000020400000000000002040C7D79E591270374000000000008046C0C7D79E591270374000000000008056C0C7D79E59127037C000000000008056C0C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000000000000000F03F000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000004000000000000008400000000000001040000000000000004000000000000000400000000000000840000000000000104000000000000000400000000000000040000000000000084000000000000010400000000000000040000000000000F8FF0000000000002340000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF00000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000405340000000000000564000000000000010400000000000001840000000000000F03F000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000000040000000000000084000000000000010400000000000000040000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF160000000100000000010100000002040000000109000000010D00000001110000000115000000011600000001170000000119000000011B00000001200000000124000000032800000001340000000338000000033C0000000146000000014A000000024E0000000353000000035700000014000000FFFFFFFF0000000007000000000000000007010000000000000001010000000100000002010000000200000008010000000300000003010000000600000004060000000600000001060000000700000001010000000800000005090000000800000002090000000900000002010000000A000000060C0000000A000000030C0000000C00000003010000000D00000009010000000E0000000A01000000110000000300000000FFFFFFFF0700000000120000000A18000000030103020000020002030200030102030203020003010203");
        byte[] geoWKB = hexStringToByteArray(
                "01070000000300000001070000000A000000010100000000000000000008400000000000000840010200000003000000000000000000F03F00000000000000000000000000000000000000000000F03F000000000000F0BF0000000000000000010800000005000000000000000000F03F00000000000008400000000000000840000000000000144000000000000010400000000000001C400000000000001C400000000000000840000000000000F03F00000000000008400103000000030000000400000000000000000000000000000000000000000000000000F03F0000000000002440000000000000F03F0000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000F03F0000000000002440000000000000F03F0000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000F03F0000000000002440000000000000F03F00000000000000000000000000000000000000000000000001040000000200000001010000000000000000000040000000000000084001010000000000000000001C40000000000000204001050000000200000001020000000200000000000000000000000000000000000040000000000000F03F000000000000F03F010200000002000000000000000000F03F0000000000000000000000000000F03F000000000000F03F01060000000200000001030000000200000005000000000000000000000000000000000000000000000000000000000000000000084000000000000008400000000000000840000000000000084000000000000000000000000000000000000000000000000004000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F0103000000010000000400000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240010900000004000000010800000005000000000000000000F03F00000000000000000000000000000000000000000000F03F0000000000002240000000000000184000000000000020400000000000001C40000000000000F0BF0000000000000000010800000003000000000000000000F0BF00000000000000000000000000001C40000000000000224000000000000024C0000000000000004001020000000400000000000000000024C0000000000000004000000000004053400000000000405340000000000000564000000000000056400000000000000040000000000000184001020000000300000000000000000000400000000000001840000000000000084000000000000008400000000000001C400000000000001C40010A00000003000000010200000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000109000000020000000102000000020000000000000000000000C7D79E59127037C00000000000000000C7D79E59127037400108000000030000000000000000000000C7D79E591270374000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C00109000000040000000102000000030000000000000000000000C7D79E59127037C00000000000001C400000000000001C400000000000000000C7D79E59127037400108000000050000000000000000000000C7D79E5912703740000000000000204000000000000020400000000000002040000000000000204000000000008046C0C7D79E591270374000000000008056C0C7D79E591270374001020000000200000000000000008056C0C7D79E591270374000000000008056C0C7D79E59127037C001080000000300000000000000008056C0C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C00103000000010000000400000000000000000000000000000000000000000000000000F03F0000000000002440000000000000F03F000000000000000000000000000000000000000000000000010700000000000000010A0000000400000001020000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010800000005000000000000000000F03F00000000000008400000000000000840000000000000144000000000000010400000000000001C400000000000001C400000000000000840000000000000F03F00000000000008400109000000020000000102000000020000000000000000000000C7D79E59127037C00000000000000000C7D79E59127037400108000000030000000000000000000000C7D79E591270374000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C00109000000040000000102000000030000000000000000000000C7D79E59127037C00000000000001C400000000000001C400000000000000000C7D79E59127037400108000000050000000000000000000000C7D79E5912703740000000000000204000000000000020400000000000002040000000000000204000000000008046C0C7D79E591270374000000000008056C0C7D79E591270374001020000000200000000000000008056C0C7D79E591270374000000000008056C0C7D79E59127037C001080000000300000000000000008056C0C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C0");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection30() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(POINT EMPTY, POINT(1 2), GEOMETRYCOLLECTION(MULTIPOINT((2 3), (7 8 9.5))))";
        byte[] geomCLR = hexStringToByteArray(
                "10000000010503000000000000000000F03F0000000000000040000000000000004000000000000008400000000000001C400000000000002040000000000000F8FF000000000000F8FF00000000000023400300000001000000000101000000010200000007000000FFFFFFFF000000000700000000FFFFFFFF01000000000000000001000000000100000007030000000100000004040000000100000001040000000200000001");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000105030000000000000000000040000000000000F03F0000000000000840000000000000004000000000000020400000000000001C40000000000000F8FF000000000000F8FF00000000000023400300000001000000000101000000010200000007000000FFFFFFFF000000000700000000FFFFFFFF01000000000000000001000000000100000007030000000100000004040000000100000001040000000200000001");
        byte[] geoWKB = hexStringToByteArray(
                "0107000000030000000104000000000000000101000000000000000000F03F000000000000004001070000000100000001040000000200000001010000000000000000000040000000000000084001010000000000000000001C400000000000002040");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection31() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(COMPOUNDCURVE((0 -23.43778, 0 23.43778)), POLYGON EMPTY, LINESTRING EMPTY, POINT(1 2), MULTIPOINT EMPTY, MULTILINESTRING EMPTY, MULTIPOLYGON EMPTY, CIRCULARSTRING EMPTY, CURVEPOLYGON EMPTY, POLYGON EMPTY, COMPOUNDCURVE EMPTY, GEOMETRYCOLLECTION EMPTY, COMPOUNDCURVE((1 1, 1 1)))";
        byte[] geomCLR = hexStringToByteArray(
                "100000000200050000000000000000000000C7D79E59127037C00000000000000000C7D79E5912703740000000000000F03F0000000000000040000000000000F03F000000000000F03F000000000000F03F000000000000F03F030000000300000000010200000003030000000E000000FFFFFFFF000000000700000000000000000900000000FFFFFFFF0300000000FFFFFFFF0200000000010000000100000000FFFFFFFF0400000000FFFFFFFF0500000000FFFFFFFF0600000000FFFFFFFF0800000000FFFFFFFF0A00000000FFFFFFFF0300000000FFFFFFFF0900000000FFFFFFFF07000000000200000009020000000202");
        byte[] geogCLR = hexStringToByteArray(
                "E6100000020005000000C7D79E59127037C00000000000000000C7D79E591270374000000000000000000000000000000040000000000000F03F000000000000F03F000000000000F03F000000000000F03F000000000000F03F030000000300000000010200000003030000000E000000FFFFFFFF000000000700000000000000000900000000FFFFFFFF0300000000FFFFFFFF0200000000010000000100000000FFFFFFFF0400000000FFFFFFFF0500000000FFFFFFFF0600000000FFFFFFFF0800000000FFFFFFFF0A00000000FFFFFFFF0300000000FFFFFFFF0900000000FFFFFFFF07000000000200000009020000000202");
        byte[] geoWKB = hexStringToByteArray(
                "01070000000D0000000109000000010000000102000000020000000000000000000000C7D79E59127037C00000000000000000C7D79E59127037400103000000000000000102000000000000000101000000000000000000F03F0000000000000040010400000000000000010500000000000000010600000000000000010800000000000000010A00000000000000010300000000000000010900000000000000010700000000000000010900000001000000010200000002000000000000000000F03F000000000000F03F000000000000F03F000000000000F03F");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection32() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(3 4), GEOMETRYCOLLECTION EMPTY, MULTIPOINT((2 3), (7 8 9.5))))";
        byte[] geomCLR = hexStringToByteArray(
                "1000000001050300000000000000000008400000000000001040000000000000004000000000000008400000000000001C400000000000002040000000000000F8FF000000000000F8FF00000000000023400300000001000000000101000000010200000007000000FFFFFFFF000000000700000000000000000701000000000000000101000000FFFFFFFF07010000000100000004040000000100000001040000000200000001");
        byte[] geogCLR = hexStringToByteArray(
                "E6100000010503000000000000000000104000000000000008400000000000000840000000000000004000000000000020400000000000001C40000000000000F8FF000000000000F8FF00000000000023400300000001000000000101000000010200000007000000FFFFFFFF000000000700000000000000000701000000000000000101000000FFFFFFFF07010000000100000004040000000100000001040000000200000001");
        byte[] geoWKB = hexStringToByteArray(
                "01070000000100000001070000000300000001010000000000000000000840000000000000104001070000000000000001040000000200000001010000000000000000000040000000000000084001010000000000000000001C400000000000002040");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection33() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(POINT(3 4), POLYGON EMPTY, POLYGON EMPTY, MULTIPOINT((2 3), (7 8 9.5)))";
        byte[] geomCLR = hexStringToByteArray(
                "1000000001050300000000000000000008400000000000001040000000000000004000000000000008400000000000001C400000000000002040000000000000F8FF000000000000F8FF00000000000023400300000001000000000101000000010200000007000000FFFFFFFF000000000700000000000000000100000000FFFFFFFF0300000000FFFFFFFF03000000000100000004040000000100000001040000000200000001");
        byte[] geogCLR = hexStringToByteArray(
                "E6100000010503000000000000000000104000000000000008400000000000000840000000000000004000000000000020400000000000001C40000000000000F8FF000000000000F8FF00000000000023400300000001000000000101000000010200000007000000FFFFFFFF000000000700000000000000000100000000FFFFFFFF0300000000FFFFFFFF03000000000100000004040000000100000001040000000200000001");
        byte[] geoWKB = hexStringToByteArray(
                "01070000000400000001010000000000000000000840000000000000104001030000000000000001030000000000000001040000000200000001010000000000000000000040000000000000084001010000000000000000001C400000000000002040");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection34() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(LINESTRING(1 0, 0 1, -1 0), POLYGON EMPTY, POLYGON EMPTY, LINESTRING(1 0, 0 1, -1 0))";
        byte[] geomCLR = hexStringToByteArray(
                "10000000010406000000000000000000F03F00000000000000000000000000000000000000000000F03F000000000000F0BF0000000000000000000000000000F03F00000000000000000000000000000000000000000000F03F000000000000F0BF0000000000000000020000000100000000010300000005000000FFFFFFFF000000000700000000000000000200000000FFFFFFFF0300000000FFFFFFFF03000000000100000002");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000104060000000000000000000000000000000000F03F000000000000F03F00000000000000000000000000000000000000000000F0BF0000000000000000000000000000F03F000000000000F03F00000000000000000000000000000000000000000000F0BF020000000100000000010300000005000000FFFFFFFF000000000700000000000000000200000000FFFFFFFF0300000000FFFFFFFF03000000000100000002");
        byte[] geoWKB = hexStringToByteArray(
                "010700000004000000010200000003000000000000000000F03F00000000000000000000000000000000000000000000F03F000000000000F0BF0000000000000000010300000000000000010300000000000000010200000003000000000000000000F03F00000000000000000000000000000000000000000000F03F000000000000F0BF0000000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection35() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(POLYGON((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1)), POLYGON EMPTY, POLYGON EMPTY, POLYGON((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1)))";
        byte[] geomCLR = hexStringToByteArray(
                "100000000104120000000000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F0000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F04000000020000000000050000000209000000000E00000005000000FFFFFFFF000000000700000000000000000300000000FFFFFFFF0300000000FFFFFFFF03000000000200000003");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000200120000000000000000000000000000000000000000000000000008400000000000000000000000000000084000000000000008400000000000000000000000000000084000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000000000000000000000000000000000008400000000000000000000000000000084000000000000008400000000000000000000000000000084000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F04000000010000000001050000000109000000010E00000005000000FFFFFFFF000000000700000000000000000300000000FFFFFFFF0300000000FFFFFFFF03000000000200000003");
        byte[] geoWKB = hexStringToByteArray(
                "01070000000400000001030000000200000005000000000000000000000000000000000000000000000000000000000000000000084000000000000008400000000000000840000000000000084000000000000000000000000000000000000000000000000004000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F01030000000000000001030000000000000001030000000200000005000000000000000000000000000000000000000000000000000000000000000000084000000000000008400000000000000840000000000000084000000000000000000000000000000000000000000000000004000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection36() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(MULTIPOINT((2 3), (7 8 9.5)), POLYGON EMPTY, POLYGON EMPTY, MULTIPOINT((2 3), (7 8 9.5)))";
        byte[] geomCLR = hexStringToByteArray(
                "10000000010504000000000000000000004000000000000008400000000000001C400000000000002040000000000000004000000000000008400000000000001C400000000000002040000000000000F8FF0000000000002340000000000000F8FF000000000000234004000000010000000001010000000102000000010300000009000000FFFFFFFF000000000700000000000000000401000000000000000101000000010000000100000000FFFFFFFF0300000000FFFFFFFF03000000000200000004060000000200000001060000000300000001");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000105040000000000000000000840000000000000004000000000000020400000000000001C400000000000000840000000000000004000000000000020400000000000001C40000000000000F8FF0000000000002340000000000000F8FF000000000000234004000000010000000001010000000102000000010300000009000000FFFFFFFF000000000700000000000000000401000000000000000101000000010000000100000000FFFFFFFF0300000000FFFFFFFF03000000000200000004060000000200000001060000000300000001");
        byte[] geoWKB = hexStringToByteArray(
                "01070000000400000001040000000200000001010000000000000000000040000000000000084001010000000000000000001C40000000000000204001030000000000000001030000000000000001040000000200000001010000000000000000000040000000000000084001010000000000000000001C400000000000002040");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection37() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(MULTILINESTRING((0 2, 1 1), (1 0, 1 1)), POLYGON EMPTY, POLYGON EMPTY, MULTILINESTRING((0 2, 1 1), (1 0, 1 1)))";
        byte[] geomCLR = hexStringToByteArray(
                "1000000001040800000000000000000000000000000000000040000000000000F03F000000000000F03F000000000000F03F0000000000000000000000000000F03F000000000000F03F00000000000000000000000000000040000000000000F03F000000000000F03F000000000000F03F0000000000000000000000000000F03F000000000000F03F04000000010000000001020000000104000000010600000009000000FFFFFFFF000000000700000000000000000501000000000000000201000000010000000200000000FFFFFFFF0300000000FFFFFFFF03000000000200000005060000000200000002060000000300000002");
        byte[] geogCLR = hexStringToByteArray(
                "E610000001040800000000000000000000400000000000000000000000000000F03F000000000000F03F0000000000000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000000000000000000F03F000000000000F03F0000000000000000000000000000F03F000000000000F03F000000000000F03F04000000010000000001020000000104000000010600000009000000FFFFFFFF000000000700000000000000000501000000000000000201000000010000000200000000FFFFFFFF0300000000FFFFFFFF03000000000200000005060000000200000002060000000300000002");
        byte[] geoWKB = hexStringToByteArray(
                "01070000000400000001050000000200000001020000000200000000000000000000000000000000000040000000000000F03F000000000000F03F010200000002000000000000000000F03F0000000000000000000000000000F03F000000000000F03F01030000000000000001030000000000000001050000000200000001020000000200000000000000000000000000000000000040000000000000F03F000000000000F03F010200000002000000000000000000F03F0000000000000000000000000000F03F000000000000F03F");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection38() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(MULTIPOLYGON(((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9))), POLYGON EMPTY, POLYGON EMPTY, MULTIPOLYGON(((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9))))";
        byte[] geomCLR = hexStringToByteArray(
                "1000000001011A000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F000000000000000000000000000000000000000000000000000000000000084000000000000008400000000000000840000000000000084000000000000000000000000000000000000000000000000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F000000000000000000000000000000000000000000000000000000000000084000000000000008400000000000000840000000000000084000000000000000000000000000000000000000000000000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001C40000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001C40000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF06000000020000000000040000000209000000020D0000000011000000021600000009000000FFFFFFFF000000000700000000000000000601000000000000000301000000020000000300000000FFFFFFFF0300000000FFFFFFFF03000000000300000006060000000300000003060000000500000003");
        byte[] geogCLR = hexStringToByteArray(
                "E610000002011A000000000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F000000000000000000000000000000000000000000000840000000000000000000000000000008400000000000000840000000000000000000000000000008400000000000000000000000000000000000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F0000000000000040000000000000F03F000000000000F03F000000000000000000000000000000000000000000000840000000000000000000000000000008400000000000000840000000000000000000000000000008400000000000000000000000000000000000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000244000000000000022400000000000002240000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001C40000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001C40000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF06000000010000000001040000000109000000010D0000000111000000011600000009000000FFFFFFFF000000000700000000000000000601000000000000000301000000020000000300000000FFFFFFFF0300000000FFFFFFFF03000000000300000006060000000300000003060000000500000003");
        byte[] geoWKB = hexStringToByteArray(
                "01070000000400000001060000000200000001030000000200000004000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F050000000000000000000000000000000000000000000000000000000000000000000840000000000000084000000000000008400000000000000840000000000000000000000000000000000000000000000000010300000001000000040000000000000000002240000000000000224000000000000022400000000000002440000000000000244000000000000022400000000000002240000000000000224001030000000000000001030000000000000001060000000200000001030000000200000004000000000000000000F03F000000000000F03F000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F0500000000000000000000000000000000000000000000000000000000000000000008400000000000000840000000000000084000000000000008400000000000000000000000000000000000000000000000000103000000010000000400000000000000000022400000000000002240000000000000224000000000000024400000000000002440000000000000224000000000000022400000000000002240");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection39() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(CIRCULARSTRING(2 1 3 4, 1 2 3, 0 7 3, 1 0 3, 2 1 3), POLYGON EMPTY, POLYGON EMPTY, CIRCULARSTRING(2 1 3 4, 1 2 3, 0 7 3, 1 0 3, 2 1 3))";
        byte[] geomCLR = hexStringToByteArray(
                "1000000002070A0000000000000000000040000000000000F03F000000000000F03F000000000000004000000000000000000000000000001C40000000000000F03F00000000000000000000000000000040000000000000F03F0000000000000040000000000000F03F000000000000F03F000000000000004000000000000000000000000000001C40000000000000F03F00000000000000000000000000000040000000000000F03F00000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000001040000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001040000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF020000000200000000020500000005000000FFFFFFFF000000000700000000000000000800000000FFFFFFFF0300000000FFFFFFFF03000000000100000008");
        byte[] geogCLR = hexStringToByteArray(
                "E610000002070A000000000000000000F03F00000000000000400000000000000040000000000000F03F0000000000001C4000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F00000000000000400000000000000040000000000000F03F0000000000001C4000000000000000000000000000000000000000000000F03F000000000000F03F000000000000004000000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000001040000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF0000000000001040000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF020000000200000000020500000005000000FFFFFFFF000000000700000000000000000800000000FFFFFFFF0300000000FFFFFFFF03000000000100000008");
        byte[] geoWKB = hexStringToByteArray(
                "0107000000040000000108000000050000000000000000000040000000000000F03F000000000000F03F000000000000004000000000000000000000000000001C40000000000000F03F00000000000000000000000000000040000000000000F03F0103000000000000000103000000000000000108000000050000000000000000000040000000000000F03F000000000000F03F000000000000004000000000000000000000000000001C40000000000000F03F00000000000000000000000000000040000000000000F03F");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection40() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(COMPOUNDCURVE((1 1, 1 1)), POLYGON EMPTY, POLYGON EMPTY, COMPOUNDCURVE((1 1, 1 1)))";
        byte[] geomCLR = hexStringToByteArray(
                "10000000020004000000000000000000F03F000000000000F03F000000000000F03F000000000000F03F000000000000F03F000000000000F03F000000000000F03F000000000000F03F020000000300000000030200000005000000FFFFFFFF000000000700000000000000000900000000FFFFFFFF0300000000FFFFFFFF03000000000100000009020000000202");
        byte[] geogCLR = hexStringToByteArray(
                "E6100000020004000000000000000000F03F000000000000F03F000000000000F03F000000000000F03F000000000000F03F000000000000F03F000000000000F03F000000000000F03F020000000300000000030200000005000000FFFFFFFF000000000700000000000000000900000000FFFFFFFF0300000000FFFFFFFF03000000000100000009020000000202");
        byte[] geoWKB = hexStringToByteArray(
                "010700000004000000010900000001000000010200000002000000000000000000F03F000000000000F03F000000000000F03F000000000000F03F010300000000000000010300000000000000010900000001000000010200000002000000000000000000F03F000000000000F03F000000000000F03F000000000000F03F");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection41() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(CURVEPOLYGON((0 0, 0 0, 0 0, 0 0)), POLYGON EMPTY, POLYGON EMPTY, CURVEPOLYGON((0 0, 0 0, 0 0, 0 0)))";
        byte[] geomCLR = hexStringToByteArray(
                "100000000200080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000100000000010400000005000000FFFFFFFF000000000700000000000000000A00000000FFFFFFFF0300000000FFFFFFFF0300000000010000000A");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000200080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000100000000010400000005000000FFFFFFFF000000000700000000000000000A00000000FFFFFFFF0300000000FFFFFFFF0300000000010000000A");
        byte[] geoWKB = hexStringToByteArray(
                "010700000004000000010A0000000100000001020000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010300000000000000010300000000000000010A0000000100000001020000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection42() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(COMPOUNDCURVE((0 -23.43778, 0 23.43778)), POLYGON EMPTY, POLYGON EMPTY, COMPOUNDCURVE((0 -23.43778, 0 23.43778)))";
        byte[] geomCLR = hexStringToByteArray(
                "100000000204040000000000000000000000C7D79E59127037C00000000000000000C7D79E59127037400000000000000000C7D79E59127037C00000000000000000C7D79E5912703740020000000300000000030200000005000000FFFFFFFF000000000700000000000000000900000000FFFFFFFF0300000000FFFFFFFF03000000000100000009020000000202");
        byte[] geogCLR = hexStringToByteArray(
                "E6100000020404000000C7D79E59127037C00000000000000000C7D79E59127037400000000000000000C7D79E59127037C00000000000000000C7D79E59127037400000000000000000020000000300000000030200000005000000FFFFFFFF000000000700000000000000000900000000FFFFFFFF0300000000FFFFFFFF03000000000100000009020000000202");
        byte[] geoWKB = hexStringToByteArray(
                "0107000000040000000109000000010000000102000000020000000000000000000000C7D79E59127037C00000000000000000C7D79E59127037400103000000000000000103000000000000000109000000010000000102000000020000000000000000000000C7D79E59127037C00000000000000000C7D79E5912703740");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests geometrycollection scenario.
     */
    @Test
    public void testGeometryCollection43() throws SQLException {
        String geoWKT = "GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(3 3 1)), POLYGON EMPTY, POLYGON EMPTY, GEOMETRYCOLLECTION(POINT(3 3 1)))";
        byte[] geomCLR = hexStringToByteArray(
                "100000000105020000000000000000000840000000000000084000000000000008400000000000000840000000000000F03F000000000000F03F020000000100000000010100000007000000FFFFFFFF000000000700000000000000000701000000000000000100000000FFFFFFFF0300000000FFFFFFFF03000000000100000007050000000100000001");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000105020000000000000000000840000000000000084000000000000008400000000000000840000000000000F03F000000000000F03F020000000100000000010100000007000000FFFFFFFF000000000700000000000000000701000000000000000100000000FFFFFFFF0300000000FFFFFFFF03000000000100000007050000000100000001");
        byte[] geoWKB = hexStringToByteArray(
                "010700000004000000010700000001000000010100000000000000000008400000000000000840010300000000000000010300000000000000010700000001000000010100000000000000000008400000000000000840");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests basic circularstring scenario.
     */
    @Test
    public void testCircularString() throws SQLException {
        String geoWKT = "CIRCULARSTRING(2 1 3 4, 1 2 3, 0 7 3, 1 0 3, 2 1 3)";
        byte[] geomCLR = hexStringToByteArray(
                "000000000207050000000000000000000040000000000000F03F000000000000F03F000000000000004000000000000000000000000000001C40000000000000F03F00000000000000000000000000000040000000000000F03F000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000001040000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF01000000020000000001000000FFFFFFFF0000000008");
        byte[] geogCLR = hexStringToByteArray(
                "E6100000020705000000000000000000F03F00000000000000400000000000000040000000000000F03F0000000000001C4000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000001040000000000000F8FF000000000000F8FF000000000000F8FF000000000000F8FF01000000020000000001000000FFFFFFFF0000000008");
        byte[] geoWKB = hexStringToByteArray(
                "0108000000050000000000000000000040000000000000F03F000000000000F03F000000000000004000000000000000000000000000001C40000000000000F03F00000000000000000000000000000040000000000000F03F");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests empty circularstring scenario.
     */
    @Test
    public void testCircularStringEmpty() throws SQLException {
        String geoWKT = "CIRCULARSTRING EMPTY";
        byte[] geomCLR = hexStringToByteArray("100000000204000000000000000001000000FFFFFFFFFFFFFFFF08");
        byte[] geogCLR = hexStringToByteArray("E61000000204000000000000000001000000FFFFFFFFFFFFFFFF08");
        byte[] geoWKB = hexStringToByteArray("010800000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests basic compoundcurve scenario.
     */
    @Test
    public void testCompoundCurve() throws SQLException {
        String geoWKT = "COMPOUNDCURVE(CIRCULARSTRING(1 0 3, 0 1 3, 9 6 3, 8 7 3, -1 0 3), CIRCULARSTRING(-1 0 3, 7 9 3, -10 2 3), (-10 2 3, 77 77 77, 88 88 88, 2 6 4), (2 6 4, 3 3 6, 7 7 1))";
        byte[] geomCLR = hexStringToByteArray(
                "0000000002050C000000000000000000F03F00000000000000000000000000000000000000000000F03F0000000000002240000000000000184000000000000020400000000000001C40000000000000F0BF00000000000000000000000000001C40000000000000224000000000000024C00000000000000040000000000040534000000000004053400000000000005640000000000000564000000000000000400000000000001840000000000000084000000000000008400000000000001C400000000000001C4000000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000405340000000000000564000000000000010400000000000001840000000000000F03F01000000030000000001000000FFFFFFFF0000000009080000000301030200000200");
        byte[] geogCLR = hexStringToByteArray(
                "E610000002050C0000000000000000000000000000000000F03F000000000000F03F0000000000000000000000000000184000000000000022400000000000001C4000000000000020400000000000000000000000000000F0BF00000000000022400000000000001C40000000000000004000000000000024C0000000000040534000000000004053400000000000005640000000000000564000000000000018400000000000000040000000000000084000000000000008400000000000001C400000000000001C4000000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000405340000000000000564000000000000010400000000000001840000000000000F03F01000000030000000001000000FFFFFFFF0000000009080000000301030200000200");
        byte[] geoWKB = hexStringToByteArray(
                "010900000004000000010800000005000000000000000000F03F00000000000000000000000000000000000000000000F03F0000000000002240000000000000184000000000000020400000000000001C40000000000000F0BF0000000000000000010800000003000000000000000000F0BF00000000000000000000000000001C40000000000000224000000000000024C0000000000000004001020000000400000000000000000024C0000000000000004000000000004053400000000000405340000000000000564000000000000056400000000000000040000000000000184001020000000300000000000000000000400000000000001840000000000000084000000000000008400000000000001C400000000000001C40");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests basic compoundcurve scenario.
     */
    @Test
    public void testCompoundCurve2() throws SQLException {
        String geoWKT = "COMPOUNDCURVE(CIRCULARSTRING(-1 0 3, 7 9 3, -10 2 3), (-10 2 3, 77 77 3, 88 88 3, 2 6 3), (2 6 3, 3 3 3, 2 6 3), CIRCULARSTRING(2 6 3, 0 1 3, 2 6 3))";
        byte[] geomCLR = hexStringToByteArray(
                "1000000002010A000000000000000000F0BF00000000000000000000000000001C40000000000000224000000000000024C0000000000000004000000000004053400000000000405340000000000000564000000000000056400000000000000040000000000000184000000000000008400000000000000840000000000000004000000000000018400000000000000000000000000000F03F00000000000000400000000000001840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084001000000030000000001000000FFFFFFFF00000000090700000003020000020003");
        byte[] geogCLR = hexStringToByteArray(
                "E610000002010A0000000000000000000000000000000000F0BF00000000000022400000000000001C40000000000000004000000000000024C00000000000405340000000000040534000000000000056400000000000005640000000000000184000000000000000400000000000000840000000000000084000000000000018400000000000000040000000000000F03F000000000000000000000000000018400000000000000040000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084000000000000008400000000000000840000000000000084001000000030000000001000000FFFFFFFF00000000090700000003020000020003");
        byte[] geoWKB = hexStringToByteArray(
                "010900000004000000010800000003000000000000000000F0BF00000000000000000000000000001C40000000000000224000000000000024C0000000000000004001020000000400000000000000000024C00000000000000040000000000040534000000000004053400000000000005640000000000000564000000000000000400000000000001840010200000003000000000000000000004000000000000018400000000000000840000000000000084000000000000000400000000000001840010800000003000000000000000000004000000000000018400000000000000000000000000000F03F00000000000000400000000000001840");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests basic compoundcurve scenario.
     */
    @Test
    public void testCompoundCurve3() throws SQLException {
        String geoWKT = "COMPOUNDCURVE((1 1, 1 1))";
        byte[] geomCLR = hexStringToByteArray(
                "10000000020002000000000000000000F03F000000000000F03F000000000000F03F000000000000F03F01000000030000000001000000FFFFFFFF00000000090100000002");
        byte[] geogCLR = hexStringToByteArray(
                "E6100000020002000000000000000000F03F000000000000F03F000000000000F03F000000000000F03F01000000030000000001000000FFFFFFFF00000000090100000002");
        byte[] geoWKB = hexStringToByteArray(
                "010900000001000000010200000002000000000000000000F03F000000000000F03F000000000000F03F000000000000F03F");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests empty compoundcurve scenario.
     */
    @Test
    public void testCompoundCurveEmpty() throws SQLException {
        String geoWKT = "COMPOUNDCURVE EMPTY";
        byte[] geomCLR = hexStringToByteArray("100000000204000000000000000001000000FFFFFFFFFFFFFFFF09");
        byte[] geogCLR = hexStringToByteArray("E61000000204000000000000000001000000FFFFFFFFFFFFFFFF09");
        byte[] geoWKB = hexStringToByteArray("010900000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests basic curvepolygon scenario.
     */
    @Test
    public void testCurvePolygon() throws SQLException {
        String geoWKT = "CURVEPOLYGON((0 0, 0 0, 0 0, 0 0), CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3), COMPOUNDCURVE((0 -23.43778, 0 23.43778), CIRCULARSTRING(0 23.43778, -45 -23.43778, 0 -23.43778)), COMPOUNDCURVE((0 -23.43778, 7 7, 0 23.43778), CIRCULARSTRING(0 23.43778, 8 8, 8 8, -45 23.43778, -90 23.43778), (-90 23.43778, -90 -23.43778), CIRCULARSTRING(-90 -23.43778, -45 -23.43778, 0 -23.43778)), COMPOUNDCURVE((0 1, 0 2), CIRCULARSTRING(0 2, 3 4, 0 1)), COMPOUNDCURVE((0 1, 0 2), CIRCULARSTRING(0 2, 3 4, 0 1)))";
        byte[] geomCLR = hexStringToByteArray(
                "1000000002001F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F00000000000008400000000000000840000000000000144000000000000010400000000000001C400000000000001C400000000000000840000000000000F03F00000000000008400000000000000000C7D79E59127037C00000000000000000C7D79E591270374000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C00000000000000000C7D79E59127037C00000000000001C400000000000001C400000000000000000C7D79E5912703740000000000000204000000000000020400000000000002040000000000000204000000000008046C0C7D79E591270374000000000008056C0C7D79E591270374000000000008056C0C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C00000000000000000000000000000F03F00000000000000000000000000000040000000000000084000000000000010400000000000000000000000000000F03F0000000000000000000000000000F03F00000000000000000000000000000040000000000000084000000000000010400000000000000000000000000000F03F06000000010000000002040000000309000000030D0000000317000000031B00000001000000FFFFFFFF000000000A0C000000020302000301020302030203");
        byte[] geogCLR = hexStringToByteArray(
                "E610000002001F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000840000000000000F03F000000000000144000000000000008400000000000001C40000000000000104000000000000008400000000000001C400000000000000840000000000000F03FC7D79E59127037C00000000000000000C7D79E59127037400000000000000000C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C000000000000000000000000000001C400000000000001C40C7D79E591270374000000000000000000000000000002040000000000000204000000000000020400000000000002040C7D79E591270374000000000008046C0C7D79E591270374000000000008056C0C7D79E59127037C000000000008056C0C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000000000000000F03F00000000000000000000000000000040000000000000000000000000000010400000000000000840000000000000F03F0000000000000000000000000000F03F00000000000000000000000000000040000000000000000000000000000010400000000000000840000000000000F03F000000000000000006000000010000000002040000000309000000030D0000000317000000031B00000001000000FFFFFFFF000000000A0C000000020302000301020302030203");
        byte[] geoWKB = hexStringToByteArray(
                "010A0000000600000001020000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010800000005000000000000000000F03F00000000000008400000000000000840000000000000144000000000000010400000000000001C400000000000001C400000000000000840000000000000F03F00000000000008400109000000020000000102000000020000000000000000000000C7D79E59127037C00000000000000000C7D79E59127037400108000000030000000000000000000000C7D79E591270374000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C00109000000040000000102000000030000000000000000000000C7D79E59127037C00000000000001C400000000000001C400000000000000000C7D79E59127037400108000000050000000000000000000000C7D79E5912703740000000000000204000000000000020400000000000002040000000000000204000000000008046C0C7D79E591270374000000000008056C0C7D79E591270374001020000000200000000000000008056C0C7D79E591270374000000000008056C0C7D79E59127037C001080000000300000000000000008056C0C7D79E59127037C000000000008046C0C7D79E59127037C00000000000000000C7D79E59127037C00109000000020000000102000000020000000000000000000000000000000000F03F0000000000000000000000000000004001080000000300000000000000000000000000000000000040000000000000084000000000000010400000000000000000000000000000F03F0109000000020000000102000000020000000000000000000000000000000000F03F0000000000000000000000000000004001080000000300000000000000000000000000000000000040000000000000084000000000000010400000000000000000000000000000F03F");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests basic curvepolygon scenario.
     */
    @Test
    public void testCurvePolygon2() throws SQLException {
        String geoWKT = "CURVEPOLYGON((0 0, 0 0, 0 0, 0 0))";
        byte[] geomCLR = hexStringToByteArray(
                "100000000200040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000001000000FFFFFFFF000000000A");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000200040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000001000000FFFFFFFF000000000A");
        byte[] geoWKB = hexStringToByteArray(
                "010A0000000100000001020000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests basic curvepolygon scenario.
     */
    @Test
    public void testCurvePolygon3() throws SQLException {
        String geoWKT = "CURVEPOLYGON(CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3))";
        byte[] geomCLR = hexStringToByteArray(
                "10000000020405000000000000000000F03F00000000000008400000000000000840000000000000144000000000000010400000000000001C400000000000001C400000000000000840000000000000F03F000000000000084001000000020000000001000000FFFFFFFF000000000A");
        byte[] geogCLR = hexStringToByteArray(
                "E61000000224050000000000000000000840000000000000F03F000000000000144000000000000008400000000000001C40000000000000104000000000000008400000000000001C400000000000000840000000000000F03F01000000020000000001000000FFFFFFFF000000000A");
        byte[] geoWKB = hexStringToByteArray(
                "010A00000001000000010800000005000000000000000000F03F00000000000008400000000000000840000000000000144000000000000010400000000000001C400000000000001C400000000000000840000000000000F03F0000000000000840");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests empty curvepolygon scenario.
     */
    @Test
    public void testCurvePolygonEmpty() throws SQLException {
        String geoWKT = "CURVEPOLYGON EMPTY";
        byte[] geomCLR = hexStringToByteArray("100000000204000000000000000001000000FFFFFFFFFFFFFFFF0A");
        byte[] geogCLR = hexStringToByteArray("E61000000204000000000000000001000000FFFFFFFFFFFFFFFF0A");
        byte[] geoWKB = hexStringToByteArray("010A00000000000000");
        validateGeometryGeography(geoWKT, geomCLR, geogCLR, geoWKB);
    }

    /**
     * Tests fullglobe scenario.
     */
    @Test
    public void testFullGlobe() throws SQLException {
        String geoWKT = "FULLGLOBE";
        byte[] geogCLR = hexStringToByteArray("E61000000224000000000000000001000000FFFFFFFFFFFFFFFF0B");
        byte[] geoWKB = hexStringToByteArray("017E000000");
        Geography geogWKT = Geography.deserialize(geogCLR);
        assertEquals(geoWKT, geogWKT.asTextZM());
        assertArrayEquals(geogWKT.STAsBinary(), geoWKB);
    }

    /**
     * Tests basic point scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testPointWkt() throws SQLException {
        beforeEachSetup();
        String geoWKT = "POINT(3 40 5 6)";
        testWkt(geoWKT);
        beforeEachSetup();
        geoWKT = "POINT EMPTY";
        testWkt(geoWKT);
    }

    /**
     * Tests basic linestring scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testLineStringWkt() throws SQLException {
        beforeEachSetup();
        String geoWKT = "LINESTRING(1 0, 0 1, -1 0)";
        testWkt(geoWKT);
        beforeEachSetup();
        geoWKT = "LINESTRING EMPTY";
        testWkt(geoWKT);
    }

    /**
     * Tests basic polygon scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testPolygonWkt() throws SQLException {
        beforeEachSetup();
        String geoWKT = "POLYGON((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1))";
        testWkt(geoWKT);
        beforeEachSetup();
        geoWKT = "POLYGON EMPTY";
        testWkt(geoWKT);
    }

    /**
     * Tests basic multipoint scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testMultiPointWkt() throws SQLException {
        beforeEachSetup();
        String geoWKT = "MULTIPOINT((2 3), (7 8 9.5))";
        testWkt(geoWKT);
        beforeEachSetup();
        geoWKT = "MULTIPOINT EMPTY";
        testWkt(geoWKT);
    }

    /**
     * Tests basic multiline scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testMultiLineStringWkt() throws SQLException {
        beforeEachSetup();
        String geoWKT = "MULTILINESTRING((0 2, 1 1), (1 0, 1 1))";
        testWkt(geoWKT);
        beforeEachSetup();
        geoWKT = "MULTILINESTRING EMPTY";
        testWkt(geoWKT);
    }

    /**
     * Tests basic multipolygon scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testMultiPolygonWkt() throws SQLException {
        beforeEachSetup();
        String geoWKT = "MULTIPOLYGON(((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)))";
        testWkt(geoWKT);
        beforeEachSetup();
        geoWKT = "MULTIPOLYGON EMPTY";
        testWkt(geoWKT);
    }

    /**
     * Tests basic geometrycollection scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testGeometryCollectionWkt() throws SQLException {
        String geoWKT;
        if (isDenaliOrLater) {
            beforeEachSetup();
            geoWKT = "GEOMETRYCOLLECTION(POINT(3 3 1), LINESTRING(1 0, 0 1, -1 0), CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3), POLYGON((0 0 2, 1 10 3, 1 0 4, 0 0 2), (0 0 2, 1 10 3, 1 0 4, 0 0 2), (0 0 2, 1 10 3, 1 0 4, 0 0 2)), MULTIPOINT((2 3), (7 8 9.5)), MULTILINESTRING((0 2, 1 1), (1 0, 1 1)), MULTIPOLYGON(((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1)), ((9 9, 9 10, 10 9, 9 9))), COMPOUNDCURVE(CIRCULARSTRING(1 0 3, 0 1 3, 9 6 3, 8 7 3, -1 0 3), CIRCULARSTRING(-1 0 3, 7 9 3, -10 2 3), (-10 2 3, 77 77 77, 88 88 88, 2 6 4), (2 6 4, 3 3 6, 7 7 1)), CURVEPOLYGON((0 0, 0 0, 0 0, 0 0), COMPOUNDCURVE((0 -23.43778, 0 23.43778), CIRCULARSTRING(0 23.43778, -45 -23.43778, 0 -23.43778)), COMPOUNDCURVE((0 -23.43778, 7 7, 0 23.43778), CIRCULARSTRING(0 23.43778, 8 8, 8 8, -45 23.43778, -90 23.43778), (-90 23.43778, -90 -23.43778), CIRCULARSTRING(-90 -23.43778, -45 -23.43778, 0 -23.43778))), POLYGON((0 0 2, 1 10 3, 1 0 4, 0 0 2)))";
            testWkt(geoWKT);
        }
        beforeEachSetup();
        geoWKT = "GEOMETRYCOLLECTION EMPTY";
        testWkt(geoWKT);
        beforeEachSetup();
        geoWKT = "GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY)";
        testWkt(geoWKT);
        beforeEachSetup();
        geoWKT = "GEOMETRYCOLLECTION(POINT(3 3 1), GEOMETRYCOLLECTION EMPTY, MULTIPOLYGON(((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1)), EMPTY, EMPTY, ((0 0, 1 1, 2 2, 0 0)), EMPTY), GEOMETRYCOLLECTION EMPTY)";
        testWkt(geoWKT);
    }

    /**
     * Tests basic circularstring scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testCircularStringWkt() throws SQLException {
        if (isDenaliOrLater) {
            beforeEachSetup();
            String geoWKT = "CIRCULARSTRING(2 1 3 4, 1 2 3, 0 7 3, 1 0 3, 2 1 3)";
            testWkt(geoWKT);
            beforeEachSetup();
            geoWKT = "CIRCULARSTRING EMPTY";
            testWkt(geoWKT);
        }
    }

    /**
     * Tests basic compoundcurve scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testCompoundCurveWkt() throws SQLException {
        if (isDenaliOrLater) {
            beforeEachSetup();
            String geoWKT = "COMPOUNDCURVE(CIRCULARSTRING(1 0 3, 0 1 3, 9 6 3, 8 7 3, -1 0 3), CIRCULARSTRING(-1 0 3, 7 9 3, -10 2 3), (-10 2 3, 77 77 77, 88 88 88, 2 6 4), (2 6 4, 3 3 6, 7 7 1))";
            testWkt(geoWKT);
            beforeEachSetup();
            geoWKT = "COMPOUNDCURVE EMPTY";
            testWkt(geoWKT);
        }
    }

    /**
     * Tests basic curvepolygon scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testCurvePolygonWkt() throws SQLException {
        if (isDenaliOrLater) {
            beforeEachSetup();
            String geoWKT = "CURVEPOLYGON((0 0, 0 0, 0 0, 0 0), CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3), COMPOUNDCURVE((0 -23.43778, 0 23.43778), CIRCULARSTRING(0 23.43778, -45 -23.43778, 0 -23.43778)), COMPOUNDCURVE((0 -23.43778, 7 7, 0 23.43778), CIRCULARSTRING(0 23.43778, 8 8, 8 8, -45 23.43778, -90 23.43778), (-90 23.43778, -90 -23.43778), CIRCULARSTRING(-90 -23.43778, -45 -23.43778, 0 -23.43778)))";
            testWkt(geoWKT);
            beforeEachSetup();
            geoWKT = "CURVEPOLYGON EMPTY";
            testWkt(geoWKT);
        }
    }

    /**
     * Tests basic fullglobe scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testFullGlobeWkt() throws SQLException {
        try (Connection con = getConnection(); Statement stmt = con.createStatement()) {
            if (isDenaliOrLater) {
                beforeEachSetup();

                String geoWKT = "FULLGLOBE";
                Geography geogWKT = Geography.STGeomFromText(geoWKT, 4326);

                try {
                    Geometry.STGeomFromText(geoWKT, 0);
                } catch (SQLServerException e) {
                    assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_illegalTypeForGeometry")),
                            e.getMessage());
                }

                try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                        "insert into " + AbstractSQLGenerator.escapeIdentifier(geogTableName) + " values (?)");) {
                    pstmt.setGeography(1, geogWKT);
                    pstmt.execute();

                    try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                            .executeQuery("select c1 from " + AbstractSQLGenerator.escapeIdentifier(geogTableName))) {
                        rs.next();
                        assertEquals(geoWKT, rs.getGeography(1).asTextZM());
                    }
                }
            }
        }
    }

    /**
     * Tests irregular string scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testIrregularCases() throws SQLException {
        beforeEachSetup();

        String geoWKT = "  GeOMETRyCOLlECTION(POINT(       3e2  2E1 1  ), GEOMETRYCOLLECTION  EmPTy  , GeometryCollection(GEometryCOLLEction(GEometryCOLLEction Empty)), "
                + "POLYGON(  (0 0 2,   1 10 3, 1 0 4,   0 0 2))  )";
        String geoWKTSS = "GEOMETRYCOLLECTION(POINT(300 20 1), GEOMETRYCOLLECTION EMPTY, GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY)), POLYGON((0 0 2, 1 10 3, 1 0 4, 0 0 2)))";

        testWkt(geoWKT, geoWKTSS);
    }

    /**
     * Tests illegal scenario against a SQL Server.
     */
    @Test
    public void testIllegalCases() throws SQLException {
        // Not enough closing bracket case
        String geoWKT = "MULTIPOLYGON(((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9))";

        try {
            testWkt(geoWKT);
        } catch (SQLServerException e) {
            MessageFormat form = new MessageFormat(TestResource.getResource("R_illegalCharWktPosition"));
            Object[] msgArgs1 = {"90"};
            assertEquals(form.format(msgArgs1), e.getMessage());
        }

        // Not enough closing and opening bracket case
        geoWKT = "MULTIPOLYGON((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9))";

        try {
            testWkt(geoWKT);
        } catch (SQLServerException e) {
            MessageFormat form = new MessageFormat(TestResource.getResource("R_illegalCharWktPosition"));
            Object[] msgArgs1 = {"14"};
            assertEquals(form.format(msgArgs1), e.getMessage());
        }

        // Too many closing bracket
        geoWKT = "MULTIPOLYGON(((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9))))";

        try {
            testWkt(geoWKT);
        } catch (SQLServerException e) {
            MessageFormat form = new MessageFormat(TestResource.getResource("R_illegalCharWktPosition"));
            Object[] msgArgs1 = {"91"};
            assertEquals(form.format(msgArgs1), e.getMessage());
        }

        // Too many opening bracket
        geoWKT = "MULTIPOLYGON((((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)))";

        try {
            testWkt(geoWKT);
        } catch (SQLServerException e) {
            MessageFormat form = new MessageFormat(TestResource.getResource("R_illegalCharWktPosition"));
            Object[] msgArgs1 = {"15"};
            assertEquals(form.format(msgArgs1), e.getMessage());
        }

        // Too many coordinates
        geoWKT = "MULTIPOLYGON(((1 1 3 4 5, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)))";

        try {
            testWkt(geoWKT);
        } catch (SQLServerException e) {
            MessageFormat form = new MessageFormat(TestResource.getResource("R_illegalCharWktPosition"));
            Object[] msgArgs1 = {"23"};
            assertEquals(form.format(msgArgs1), e.getMessage());
        }

        // Too little coordinates
        geoWKT = "MULTIPOLYGON(((1 , 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)))";

        try {
            testWkt(geoWKT);
        } catch (SQLServerException e) {
            MessageFormat form = new MessageFormat(TestResource.getResource("R_illegalCharWktPosition"));
            Object[] msgArgs1 = {"17"};
            assertEquals(form.format(msgArgs1), e.getMessage());
        }

        // Incorrect data type
        geoWKT = "IvnalidPolygon(((1 , 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)))";

        try {
            testWkt(geoWKT);
        } catch (SQLServerException e) {
            MessageFormat form = new MessageFormat(TestResource.getResource("R_illegalCharWktPosition"));
            Object[] msgArgs1 = {"14"};
            assertEquals(form.format(msgArgs1), e.getMessage());
        }

        // too many commas
        geoWKT = "MULTIPOLYGON(((1 1, 1 2, 2 1, 1 1),, (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)))";

        try {
            testWkt(geoWKT);
        } catch (SQLServerException e) {
            MessageFormat form = new MessageFormat(TestResource.getResource("R_illegalCharWktPosition"));
            Object[] msgArgs1 = {"35"};
            assertEquals(form.format(msgArgs1), e.getMessage());
        }

        // too little commas
        geoWKT = "MULTIPOLYGON(((1 1, 1 2, 2 1, 1 1) (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)))";

        try {
            testWkt(geoWKT);
        } catch (SQLServerException e) {
            MessageFormat form = new MessageFormat(TestResource.getResource("R_illegalCharWktPosition"));
            Object[] msgArgs1 = {"35"};
            assertEquals(form.format(msgArgs1), e.getMessage());
        }
    }

    /**
     * Tests all basic scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testAllTypes() throws SQLException {
        if (isDenaliOrLater) {
            beforeEachSetup();

            String geoWKTPoint = "POINT(30 12.12312312 5 6)";
            String geoWKTLineString = "LINESTRING(1 1 0 0, 2 4 3 0, 3 9 123 332)";
            String geoWKTCircularString = "CIRCULARSTRING(1 1, 2 4, 3 9)";
            String geoWKTCompoundCurve = "COMPOUNDCURVE((1 1, 1 3), (1 3, 3 3), (3 3, 3 1), (3 1, 1 1))";
            String geoWKTCurvePolygon = "CURVEPOLYGON(CIRCULARSTRING(2 4, 4 2, 6 4, 4 6, 2 4))";
            String geoWKTPolygon = "POLYGON((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1))";
            String geoWKTMultiPoint = "MULTIPOINT((2 3), (7 8 9.5 4))";
            String geoWKTMultiLineString = "MULTILINESTRING((0 2, 1 1), (1 0, 1 1))";
            String geoWKTMultiPolygon = "MULTIPOLYGON(((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1)), ((9 9, 9 10, 10 9, 9 9)))";
            String geoWKTGeometryCollection = "GEOMETRYCOLLECTION(POLYGON((0 0 2, 1 10 3, 1 0 4, 0 0 2)), POINT(3 3 1 2.5), LINESTRING(1 0, 0 1, -1 0), GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(1 2 3 4))), GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY), CURVEPOLYGON((0 0, 0 0, 0 0, 0 0), CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3), COMPOUNDCURVE((0 -23.43778, 0 23.43778), CIRCULARSTRING(0 23.43778, -45 -23.43778, 0 -23.43778)), COMPOUNDCURVE((0 -23.43778, 7 7, 0 23.43778), CIRCULARSTRING(0 23.43778, 8 8, 8 8, -45 23.43778, -90 23.43778), (-90 23.43778, -90 -23.43778), CIRCULARSTRING(-90 -23.43778, -45 -23.43778, 0 -23.43778))))";

            List<String> geoWKTList = new ArrayList<String>();

            geoWKTList.add(geoWKTPoint);
            geoWKTList.add(geoWKTLineString);
            geoWKTList.add(geoWKTCircularString);
            geoWKTList.add(geoWKTCompoundCurve);
            geoWKTList.add(geoWKTCurvePolygon);
            geoWKTList.add(geoWKTPolygon);
            geoWKTList.add(geoWKTMultiPoint);
            geoWKTList.add(geoWKTMultiLineString);
            geoWKTList.add(geoWKTMultiPolygon);
            geoWKTList.add(geoWKTGeometryCollection);

            Geometry geomWKT;
            Geography geogWKT;

            // Geometry
            try (Connection con = getConnection(); Statement stmt = con.createStatement()) {

                try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                        "insert into " + AbstractSQLGenerator.escapeIdentifier(geomTableName) + " values (?)")) {
                    geomWKT = Geometry.STGeomFromText(geoWKTPoint, 0);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTLineString, 0);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTCircularString, 0);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTCompoundCurve, 0);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTCurvePolygon, 0);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTPolygon, 0);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTMultiPoint, 0);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTMultiLineString, 0);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTMultiPolygon, 0);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTGeometryCollection, 0);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.executeUpdate();

                    try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                            .executeQuery("select c1 from " + AbstractSQLGenerator.escapeIdentifier(geomTableName))) {
                        for (int i = 0; i < geoWKTList.size(); i++) {
                            rs.next();
                            assertEquals(geoWKTList.get(i), rs.getGeometry(1).asTextZM());
                        }
                    }
                }

                // Geography
                try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                        "insert into " + AbstractSQLGenerator.escapeIdentifier(geogTableName) + " values (?)")) {
                    geogWKT = Geography.STGeomFromText(geoWKTPoint, 4326);
                    pstmt.setGeography(1, geogWKT);

                    pstmt.executeUpdate();

                    geogWKT = Geography.STGeomFromText(geoWKTLineString, 4326);
                    pstmt.setGeography(1, geogWKT);

                    pstmt.executeUpdate();

                    geogWKT = Geography.STGeomFromText(geoWKTCircularString, 4326);
                    pstmt.setGeography(1, geogWKT);

                    pstmt.executeUpdate();

                    geogWKT = Geography.STGeomFromText(geoWKTCompoundCurve, 4326);
                    pstmt.setGeography(1, geogWKT);

                    pstmt.executeUpdate();

                    geogWKT = Geography.STGeomFromText(geoWKTCurvePolygon, 4326);
                    pstmt.setGeography(1, geogWKT);

                    pstmt.executeUpdate();

                    geogWKT = Geography.STGeomFromText(geoWKTPolygon, 4326);
                    pstmt.setGeography(1, geogWKT);

                    pstmt.executeUpdate();

                    geogWKT = Geography.STGeomFromText(geoWKTMultiPoint, 4326);
                    pstmt.setGeography(1, geogWKT);

                    pstmt.executeUpdate();

                    geogWKT = Geography.STGeomFromText(geoWKTMultiLineString, 4326);
                    pstmt.setGeography(1, geogWKT);

                    pstmt.executeUpdate();

                    geogWKT = Geography.STGeomFromText(geoWKTMultiPolygon, 4326);
                    pstmt.setGeography(1, geogWKT);

                    pstmt.executeUpdate();

                    geogWKT = Geography.STGeomFromText(geoWKTGeometryCollection, 4326);
                    pstmt.setGeography(1, geogWKT);

                    pstmt.executeUpdate();

                    try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                            .executeQuery("select c1 from " + AbstractSQLGenerator.escapeIdentifier(geogTableName))) {
                        for (int i = 0; i < geoWKTList.size(); i++) {
                            rs.next();
                            assertEquals(geoWKTList.get(i), rs.getGeography(1).asTextZM());
                        }
                    }
                }
            }
        }
    }

    /**
     * Tests all mixed scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testMixedAllTypes() throws SQLException {
        if (isDenaliOrLater) {
            beforeEachSetupSpatialDatatype();

            String geoWKTPoint = "POINT(30 12.12312312 0)";
            String geoWKTLineString = "LINESTRING(1 1, 2 4 3, 3 9 123 332)";
            String geoWKTCircularString = "CIRCULARSTRING(1 1, 2 4, 3 9)";
            String geoWKTCompoundCurve = "COMPOUNDCURVE((1 1, 1 3), (1 3, 3 3), (3 3, 3 1), (3 1, 1 1))";
            String geoWKTCurvePolygon = "CURVEPOLYGON(CIRCULARSTRING(2 4, 4 2, 6 4, 4 6, 2 4))";
            String geoWKTPolygon = "POLYGON((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1))";
            String geoWKTMultiPoint = "MULTIPOINT((2 3), (7 8 9.5))";
            String geoWKTMultiLineString = "MULTILINESTRING((0 2, 1 1), (1 0, 1 1))";
            String geoWKTMultiPolygon = "MULTIPOLYGON(((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1)), ((9 9, 9 10, 10 9, 9 9)))";
            String geoWKTGeometryCollection = "GEOMETRYCOLLECTION(POLYGON((0 0 2, 1 10 3, 1 0 4, 0 0 2)), POINT(3 3 1 2.5), LINESTRING(1 0, 0 1, -1 0), GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(1 2 3 4))), GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY), CURVEPOLYGON((0 0, 0 0, 0 0, 0 0), CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3), COMPOUNDCURVE((0 -23.43778, 0 23.43778), CIRCULARSTRING(0 23.43778, -45 -23.43778, 0 -23.43778)), COMPOUNDCURVE((0 -23.43778, 7 7, 0 23.43778), CIRCULARSTRING(0 23.43778, 8 8, 8 8, -45 23.43778, -90 23.43778), (-90 23.43778, -90 -23.43778), CIRCULARSTRING(-90 -23.43778, -45 -23.43778, 0 -23.43778))))";

            String s = "some string";
            Double d = 31.34;
            int i2 = 5;

            List<String> geoWKTList = new ArrayList<String>();

            geoWKTList.add(geoWKTPoint);
            geoWKTList.add(geoWKTLineString);
            geoWKTList.add(geoWKTCircularString);
            geoWKTList.add(geoWKTCompoundCurve);
            geoWKTList.add(geoWKTCurvePolygon);
            geoWKTList.add(geoWKTPolygon);
            geoWKTList.add(geoWKTMultiPoint);
            geoWKTList.add(geoWKTMultiLineString);
            geoWKTList.add(geoWKTMultiPolygon);
            geoWKTList.add(geoWKTGeometryCollection);

            Geometry geomWKT;
            Geography geogWKT;

            try (Connection con = getConnection(); Statement stmt = con.createStatement()) {
                try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                        "insert into " + AbstractSQLGenerator.escapeIdentifier(spatialDatatypeTableName)
                                + " values (?, ?, ?, ?, ?)");) {
                    geomWKT = Geometry.STGeomFromText(geoWKTPoint, 0);
                    geogWKT = Geography.STGeomFromText(geoWKTPoint, 4326);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.setGeography(2, geogWKT);
                    pstmt.setString(3, s);
                    pstmt.setDouble(4, d);
                    pstmt.setInt(5, i2);

                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTLineString, 0);
                    geogWKT = Geography.STGeomFromText(geoWKTLineString, 4326);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.setGeography(2, geogWKT);
                    pstmt.setString(3, s);
                    pstmt.setDouble(4, d);
                    pstmt.setInt(5, i2);

                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTCircularString, 0);
                    geogWKT = Geography.STGeomFromText(geoWKTCircularString, 4326);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.setGeography(2, geogWKT);
                    pstmt.setString(3, s);
                    pstmt.setDouble(4, d);
                    pstmt.setInt(5, i2);

                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTCompoundCurve, 0);
                    geogWKT = Geography.STGeomFromText(geoWKTCompoundCurve, 4326);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.setGeography(2, geogWKT);
                    pstmt.setString(3, s);
                    pstmt.setDouble(4, d);
                    pstmt.setInt(5, i2);

                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTCurvePolygon, 0);
                    geogWKT = Geography.STGeomFromText(geoWKTCurvePolygon, 4326);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.setGeography(2, geogWKT);
                    pstmt.setString(3, s);
                    pstmt.setDouble(4, d);
                    pstmt.setInt(5, i2);

                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTPolygon, 0);
                    geogWKT = Geography.STGeomFromText(geoWKTPolygon, 4326);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.setGeography(2, geogWKT);
                    pstmt.setString(3, s);
                    pstmt.setDouble(4, d);
                    pstmt.setInt(5, i2);

                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTMultiPoint, 0);
                    geogWKT = Geography.STGeomFromText(geoWKTMultiPoint, 4326);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.setGeography(2, geogWKT);
                    pstmt.setString(3, s);
                    pstmt.setDouble(4, d);
                    pstmt.setInt(5, i2);

                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTMultiLineString, 0);
                    geogWKT = Geography.STGeomFromText(geoWKTMultiLineString, 4326);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.setGeography(2, geogWKT);
                    pstmt.setString(3, s);
                    pstmt.setDouble(4, d);
                    pstmt.setInt(5, i2);

                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTMultiPolygon, 0);
                    geogWKT = Geography.STGeomFromText(geoWKTMultiPolygon, 4326);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.setGeography(2, geogWKT);
                    pstmt.setString(3, s);
                    pstmt.setDouble(4, d);
                    pstmt.setInt(5, i2);

                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTGeometryCollection, 0);
                    geogWKT = Geography.STGeomFromText(geoWKTGeometryCollection, 4326);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.setGeography(2, geogWKT);
                    pstmt.setString(3, s);
                    pstmt.setDouble(4, d);
                    pstmt.setInt(5, i2);

                    pstmt.executeUpdate();

                    try (SQLServerResultSet rs = (SQLServerResultSet) stmt.executeQuery(
                            "select * from " + AbstractSQLGenerator.escapeIdentifier(spatialDatatypeTableName))) {
                        for (int i = 0; i < geoWKTList.size(); i++) {
                            rs.next();
                            assertEquals(geoWKTList.get(i), rs.getGeometry(1).asTextZM());
                            assertEquals(geoWKTList.get(i), rs.getGeography(2).asTextZM());
                            assertEquals(s, rs.getString(3));
                            assertEquals(d, (Double) rs.getDouble(4));
                            assertEquals(i2, rs.getInt(5));
                        }
                    }
                }
            }
        }
    }

    /**
     * Tests decimal rounding scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testDecimalRounding() throws SQLException {
        beforeEachSetup();

        String geoWKT = "POINT(3 40.7777777777777777777 5 6)";
        String geoWKTSS = "POINT(3 40.77777777777778 5 6)";

        testWkt(geoWKT, geoWKTSS);
    }

    /**
     * Tests advanced geometrycollection scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testParse() throws SQLException {
        beforeEachSetup();

        String geoWKT = "GEOMETRYCOLLECTION(POINT(300 20 1), GEOMETRYCOLLECTION EMPTY, GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY)), POLYGON((0 0 2, 1 10 3, 1 0 4, 0 0 2)))";

        Geometry geomWKT = Geometry.parse(geoWKT);
        Geography geogWKT = Geography.parse(geoWKT);

        try (Connection con = getConnection(); Statement stmt = con.createStatement()) {

            try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                    "insert into " + AbstractSQLGenerator.escapeIdentifier(geomTableName) + " values (?)");) {
                pstmt.setGeometry(1, geomWKT);
                pstmt.execute();

                try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                        .executeQuery("select c1 from " + AbstractSQLGenerator.escapeIdentifier(geomTableName))) {
                    rs.next();
                    assertEquals(geoWKT, rs.getGeometry(1).asTextZM());
                    assertEquals(0, rs.getGeometry(1).getSrid());
                }
            }

            try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                    "insert into " + AbstractSQLGenerator.escapeIdentifier(geogTableName) + " values (?)");) {
                pstmt.setGeography(1, geogWKT);
                pstmt.execute();

                try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                        .executeQuery("select c1 from " + AbstractSQLGenerator.escapeIdentifier(geogTableName))) {
                    rs.next();
                    assertEquals(geoWKT, rs.getGeography(1).asTextZM());
                    assertEquals(4326, rs.getGeography(1).getSrid());
                }
            }
        }

    }

    /**
     * Tests basic point scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testSendBasicPoint() throws SQLException {
        beforeEachSetup();

        String geoWKT = "POINT(1 2)";

        Geometry geomWKT = Geometry.point(1, 2, 0);
        Geography geogWKT = Geography.point(2, 1, 4326);

        try (Connection con = getConnection(); Statement stmt = con.createStatement()) {

            try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                    "insert into " + AbstractSQLGenerator.escapeIdentifier(geomTableName) + " values (?)");) {
                pstmt.setGeometry(1, geomWKT);
                pstmt.execute();

                try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                        .executeQuery("select c1 from " + AbstractSQLGenerator.escapeIdentifier(geomTableName))) {
                    rs.next();
                    assertEquals(geoWKT, rs.getGeometry(1).asTextZM());
                    assertEquals(0, rs.getGeometry(1).getSrid());
                }
            }

            try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                    "insert into " + AbstractSQLGenerator.escapeIdentifier(geogTableName) + " values (?)");) {
                pstmt.setGeography(1, geogWKT);
                pstmt.execute();

                try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                        .executeQuery("select c1 from " + AbstractSQLGenerator.escapeIdentifier(geogTableName))) {
                    rs.next();
                    assertEquals(geoWKT, rs.getGeography(1).asTextZM());
                    assertEquals(4326, rs.getGeography(1).getSrid());
                }
            }
        }
    }

    /**
     * Tests setObject scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testSetObject() throws SQLException {
        beforeEachSetup();

        String geoWKT = "POINT(1 2)";

        Geometry geomWKT = Geometry.point(1, 2, 0);
        Geography geogWKT = Geography.point(2, 1, 4326);

        try (Connection con = getConnection(); Statement stmt = con.createStatement()) {

            try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                    "insert into " + AbstractSQLGenerator.escapeIdentifier(geomTableName) + " values (?)");) {
                pstmt.setObject(1, geomWKT);
                pstmt.execute();

                try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                        .executeQuery("select c1 from " + AbstractSQLGenerator.escapeIdentifier(geomTableName))) {
                    rs.next();
                    assertEquals(geoWKT, rs.getGeometry(1).asTextZM());
                    assertEquals(0, rs.getGeometry(1).getSrid());
                }
            }

            try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                    "insert into " + AbstractSQLGenerator.escapeIdentifier(geogTableName) + " values (?)");) {
                pstmt.setObject(1, geogWKT);
                pstmt.execute();

                try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                        .executeQuery("select c1 from " + AbstractSQLGenerator.escapeIdentifier(geogTableName))) {
                    rs.next();
                    assertEquals(geoWKT, rs.getGeography(1).asTextZM());
                    assertEquals(4326, rs.getGeography(1).getSrid());
                }
            }
        }
    }

    /**
     * Tests STAsText scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testSTAsText() throws SQLException {
        beforeEachSetup();

        String geoWKT = "GEOMETRYCOLLECTION(POINT(300 20 1), GEOMETRYCOLLECTION EMPTY, GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY)), POLYGON((0 0 2, 1 10 3, 1 0 4, 0 0 2)))";
        String geoWKTSS = "GEOMETRYCOLLECTION(POINT(300 20), GEOMETRYCOLLECTION EMPTY, GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY)), POLYGON((0 0, 1 10, 1 0, 0 0)))";

        Geometry geomWKT = Geometry.STGeomFromText(geoWKT, 0);
        Geography geogWKT = Geography.STGeomFromText(geoWKT, 4326);

        try (Connection con = getConnection(); Statement stmt = con.createStatement()) {

            try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                    "insert into " + AbstractSQLGenerator.escapeIdentifier(geomTableName) + " values (?)");) {
                pstmt.setGeometry(1, geomWKT);
                pstmt.execute();

                try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                        .executeQuery("select c1 from " + AbstractSQLGenerator.escapeIdentifier(geomTableName))) {
                    rs.next();
                    assertEquals(geoWKTSS, rs.getGeometry(1).STAsText());
                }
            }

            try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                    "insert into " + AbstractSQLGenerator.escapeIdentifier(geogTableName) + " values (?)");) {
                pstmt.setGeography(1, geogWKT);
                pstmt.execute();

                try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                        .executeQuery("select c1 from " + AbstractSQLGenerator.escapeIdentifier(geogTableName))) {
                    rs.next();
                    assertEquals(geoWKTSS, rs.getGeography(1).STAsText());
                }
            }
        }
    }

    /**
     * Tests geometry metadata scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testCheckGeomMetaData() throws SQLException {
        beforeEachSetup();

        try (Connection con = getConnection(); Statement stmt = con.createStatement();
                SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) connection.prepareStatement(
                        "INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(geomTableName) + " (c1) VALUES (?)")) {
            ParameterMetaData paramMetaData = pstmt.getParameterMetaData();
            Geometry g = Geometry.STGeomFromText("POINT (1 2 3 4)", 0);
            pstmt.setGeometry(1, g);
            pstmt.execute();

            int sqlType = paramMetaData.getParameterType(1);
            String sqlTypeName = paramMetaData.getParameterTypeName(1);
            assertEquals(-157, sqlType);
            assertEquals("geometry", sqlTypeName);
            try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                    .executeQuery("select * from " + AbstractSQLGenerator.escapeIdentifier(geomTableName))) {
                ResultSetMetaData rsmd = rs.getMetaData();
                assertEquals(-157, rsmd.getColumnType(1));
            }
        }
    }

    /**
     * Tests geography metadata scenario against a SQL Server.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testCheckGeogMetaData() throws SQLException {
        beforeEachSetup();

        try (Connection con = getConnection(); Statement stmt = con.createStatement();
                SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) connection.prepareStatement(
                        "INSERT INTO " + AbstractSQLGenerator.escapeIdentifier(geogTableName) + " (c1) VALUES (?)")) {
            ParameterMetaData paramMetaData = pstmt.getParameterMetaData();
            Geography g = Geography.STGeomFromText("POINT (1 2 3 4)", 4326);
            pstmt.setGeography(1, g);
            pstmt.execute();

            int sqlType = paramMetaData.getParameterType(1);
            String sqlTypeName = paramMetaData.getParameterTypeName(1);
            assertEquals(-158, sqlType);
            assertEquals(sqlTypeName, "geography");
            try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                    .executeQuery("select * from " + AbstractSQLGenerator.escapeIdentifier(geogTableName))) {
                ResultSetMetaData rsmd = rs.getMetaData();
                assertEquals(-158, rsmd.getColumnType(1));
            }
        }
    }

    /**
     * Tests getY scenario.
     */
    @Test
    public void testGetXGetY() throws SQLException {
        Geometry geom = Geometry.STGeomFromText("POINT (1 2 3 4)", 0);
        Geography geog = Geography.STGeomFromText("POINT (1 2 3 4)", 4326);

        double x = geom.getX();
        double y = geom.getY();
        assertEquals(1, x);
        assertEquals(2, y);

        x = geog.getLatitude();
        y = geog.getLongitude();
        assertEquals(2, x);
        assertEquals(1, y);
    }

    /**
     * Tests null scenario.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testNull() throws SQLException {
        if (isDenaliOrLater) {
            beforeEachSetupSpatialDatatype();

            String geoWKTPoint = "POINT(30 12.12312312 NULL 6)";
            String geoWKTLineString = "LINESTRING(1 1 NULL NULL, 2 4 0 42, 3 9 NULL 332)";

            String geoWKTPointExpected = "POINT(30 12.12312312 NULL 6)";
            String geoWKTLineStringExpected = "LINESTRING(1 1, 2 4 0 42, 3 9 NULL 332)";

            String s = "some string";
            Double d = 31.34;
            int i2 = 5;

            List<String> geoWKTList = new ArrayList<String>();

            geoWKTList.add(geoWKTPoint);
            geoWKTList.add(geoWKTLineString);

            List<String> geoWKTListExpected = new ArrayList<String>();

            geoWKTListExpected.add(geoWKTPointExpected);
            geoWKTListExpected.add(geoWKTLineStringExpected);

            Geometry geomWKT;
            Geography geogWKT;

            try (Connection con = getConnection(); Statement stmt = con.createStatement()) {

                try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                        "insert into " + AbstractSQLGenerator.escapeIdentifier(spatialDatatypeTableName)
                                + " values (?, ?, ?, ?, ?)");) {
                    geomWKT = Geometry.STGeomFromText(geoWKTPoint, 0);
                    geogWKT = Geography.STGeomFromText(geoWKTPoint, 4326);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.setGeography(2, geogWKT);
                    pstmt.setString(3, s);
                    pstmt.setDouble(4, d);
                    pstmt.setInt(5, i2);

                    pstmt.executeUpdate();

                    geomWKT = Geometry.STGeomFromText(geoWKTLineString, 0);
                    geogWKT = Geography.STGeomFromText(geoWKTLineString, 4326);
                    pstmt.setGeometry(1, geomWKT);
                    pstmt.setGeography(2, geogWKT);
                    pstmt.setString(3, s);
                    pstmt.setDouble(4, d);
                    pstmt.setInt(5, i2);

                    pstmt.executeUpdate();

                    try (SQLServerResultSet rs = (SQLServerResultSet) stmt.executeQuery(
                            "select * from " + AbstractSQLGenerator.escapeIdentifier(spatialDatatypeTableName))) {
                        for (int i = 0; i < geoWKTList.size(); i++) {
                            rs.next();
                            assertEquals(geoWKTListExpected.get(i), rs.getGeometry(1).asTextZM());
                            assertEquals(geoWKTListExpected.get(i), rs.getGeography(2).asTextZM());
                            assertEquals(s, rs.getString(3));
                            assertEquals(d, (Double) rs.getDouble(4));
                            assertEquals(i2, rs.getInt(5));
                        }
                    }
                }
            }
        }
    }

    /**
     * Tests wrong type scenario.
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testWrongtype() throws SQLException {
        beforeEachSetup();

        Geometry geomWKT = Geometry.point(1, 2, 0);
        Geography geogWKT = Geography.point(2, 1, 4326);

        try (Connection con = getConnection(); Statement stmt = con.createStatement()) {

            try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                    "insert into " + AbstractSQLGenerator.escapeIdentifier(geomTableName) + " values (?)");) {
                pstmt.setGeometry(1, geomWKT);
                pstmt.execute();

                try {
                    SQLServerResultSet rs = (SQLServerResultSet) stmt
                            .executeQuery("select * from " + AbstractSQLGenerator.escapeIdentifier(geomTableName));
                    rs.next();
                    rs.getGeography(1); // should fail
                    fail();
                } catch (SQLServerException e) {
                    assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_unsupportedConversionFromTo")),
                            e.getMessage());
                }
            }

            try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                    "insert into " + AbstractSQLGenerator.escapeIdentifier(geogTableName) + " values (?)");) {
                pstmt.setGeography(1, geogWKT);
                pstmt.execute();

                try {
                    SQLServerResultSet rs = (SQLServerResultSet) stmt
                            .executeQuery("select * from " + AbstractSQLGenerator.escapeIdentifier(geogTableName));
                    rs.next();
                    rs.getGeometry(1); // should fail
                    fail();
                } catch (SQLServerException e) {
                    assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_unsupportedConversionFromTo")),
                            e.getMessage());
                }
            }
        }
    }

    /**
     * Tests large WKT (Geography/Geometry cases that end up with more than 8000 bytes) cases.
     * 
     * @throws SQLException
     */
    @Test
    @Tag(Constants.xAzureSQLDW)
    public void testLargeCases() throws SQLException {
        String wktLargeGeometry = "MULTIPOLYGON(((238510.319 560225.328, 238509.942 560225.021, 238522.621 560213.046, 238537.167 560199.423, 238537.415 560199.191, 238539.784 560198.151, 238543.891 560193.921, 238552.898 560186.639, 238558.987 560183.617, 238560.947 560182.093, 238561.848 560180.481, 238562.623 560178.22, 238562.427 560176.072, 238561.409 560173.929, 238555.694 560162.32, 238551.821 560153.393, 238547.821 560144.089, 238539.619 560126.983, 238534.428 560116.124, 238528.784 560108.795, 238527.261 560098.877, 238527.954 560096.965, 238526.065 560079.053, 238523.789 560062.407, 238520.604 560053.256, 238517.119 560039.845, 238515.228 560027.656, 238515.372 560025.477, 238516.685 560022.118, 238519.73 560013.764, 238521.004 560009.246, 238522.181 560006.651, 238523.36 560005.312, 238524.35 560004.171, 238524.479 560004.041, 238526.717 560002.86, 238528.55 560000.958, 238534.171 559997.044, 238536.968 559994.21, 238539.376 559989.861, 238540.385 559986.164, 238539.773 559982.708, 238538.813 559979.717, 238535.943 559974.781, 238530.056 559967.52, 238522.452 559957.954, 238517.345 559951.762, 238502.739 559937.228, 238494.775 559929.976, 238489.548 559926.191, 238483.514 559920.837, 238480.819 559918.804, 238479.911 559917.359, 238479.427 559915.807, 238479.455 559914.939, 238478.987 559910.236, 238478.792 559908.361, 238479.369 559906.186, 238480.682 559904.082, 238482.836 559902.196, 238489.598 559896.056, 238496.768 559891.384, 238507.836 559885.944, 238513.119 559883.589, 238515.161 559881.715, 238516.825 559878.711, 238518.145 559875.191, 238518.176 559872.041, 238517.28 559867.219, 238516.377 559864.098, 238516.066 559862.929, 238515.587 559858.435, 238511.726 559846.403, 238510.25 559840.974, 238507.189 559832.2, 238503.774 559824.052, 238498.267 559812.468, 238493.094 559802.542, 238490.908 559799.344, 238489.309 559797.575, 238487.14 559796.565, 238483.98 559794.187, 238475.062 559790.214, 238472.721 559788.81, 238467.763 559786.985, 238464.063 559785.43, 238458.645 559782.826, 238449.674 559779.269, 238444.796 559776.821, 238441.305 559775.567, 238438.983 559774.115, 238436.7 559771.862, 238435.163 559769.517, 238434.292 559766.722, 238433.982 559763.329, 238434.269 559757.989, 238435.968 559753.364, 238439.153 559746.045, 238440.166 559741.642, 238440.542 559736.772, 238438.907 559727.138, 238437.177 559714.958, 238436.431 559709.05, 238435.875 559701.962, 238434.823 559690.7, 238434.967 559688.794, 238435.325 559685.226, 238434.752 559679.44, 238433.169 559668.135, 238430.344 559654.435, 238428.923 559643.14, 238427.495 559638.002, 238425.878 559634.045, 238425.22 559632.957, 238423.704 559629.979, 238417.496 559620.468, 238412.385 559612.475, 238410.059 559608.24, 238404.908 559598.814, 238404.537 559595.016, 238403.782 559585.507, 238403.718 559579.811, 238403.173 559574.363, 238403.88 559569.861, 238404.466 559568.543, 238406.451 559563.046, 238409.863 559555.708, 238413.05 559549.646, 238415.935 559544.775, 238417.546 559539.677, 238417.885 559537.411, 238417.634 559535.404, 238416.781 559533.817, 238414.228 559531.839, 238408.051 559528.391, 238401.591 559524.126, 238398.827 559522.829, 238396.438 559522.66, 238389.036 559519.553, 238382.014 559516.594, 238378.098 559512.938, 238376.336 559510.888, 238375.41 559509.56, 238375.428 559507.829, 238375.916 559505.543, 238376.723 559502.641, 238377.951 559497.123, 238378.082 559489.814, 238378.133 559480.892, 238378.418 559471.787, 238379.478 559466.421, 238380.917 559462.185, 238380.909 559458.854, 238381.421 559455.729, 238381.087 559454.071, 238379.971 559452.6, 238379.021 559451.683, 238376.037 559450.247, 238372.928 559449.415, 238370.472 559449.001, 238361.499 559446.426, 238357.012 559444.73, 238350.377 559441.813, 238331.412 559437.737, 238324.696 559435.388, 238313.976 559431.422, 238307.721 559430.125, 238303.299 559428.181, 238298.188 559427.168, 238292.64 559423.366, 238288.804 559420.343, 238284.602 559416.304, 238279.331 559410.811, 238277.313 559408.36, 238277.15 559408.161, 238275.139 559404.377, 238266.906 559394.184, 238263.367 559390.403, 238261.079 559388.583, 238256.642 559385.979, 238254.171 559384.633, 238251.615 559383.636, 238248.462 559383.331, 238241.193 559382.675, 238236.734 559383.062, 238235.822 559383.47, 238228.571 559387.346, 238222.008 559391.163, 238217.439 559393.088, 238212.154 559395.169, 238208.588 559396.34, 238200.919 559397.546, 238194.965 559398.548, 238189.57 559398.678, 238182.32 559397.975, 238175.447 559396.165, 238167.977 559394.068, 238161.157 559392.823, 238156.185 559391.591, 238151.499 559389.489, 238144.851 559386.131, 238143.161 559384.872, 238139.808 559383.285, 238135.737 559381.265, 238132.984 559380.355, 238131.227 559380.106, 238129.143 559379.019, 238127.298 559377.318, 238125.603 559375.238, 238124.741 559373.539, 238123.568 559371.936, 238121.576 559370.612, 238119.942 559369.212, 238118.817 559367.627, 238118.006 559365.512, 238118.121 559363.266, 238119.082 559359.552, 238121.323 559355.628, 238124.54 559350.886, 238128.161 559346.084, 238132.359 559341.341, 238136.131 559336.434, 238137.875 559332.807, 238139.727 559326.114, 238141.05 559319.379, 238141.615 559314.582, 238142.063 559310.504, 238141.679 559308.282, 238140.634 559306.347, 238139.321 559304.963, 238136.629 559302.221, 238123.407 559289.59, 238116.216 559282.313, 238108.774 559276.518, 238102.742 559272.419, 238095.364 559267.575, 238084.615 559261.036, 238071.831 559252.72, 238061.479 559247.534, 238051.31 559241.602, 238042.511 559235.932, 238035.44 559230.719, 238030.894 559226.164, 238026.857 559223.661, 238026.743 559223.493, 238020.814 559214.704, 238017.349 559211.007, 238012.859 559205.056, 238011.441 559202.267, 238007.803 559195.668, 238003.712 559189.109, 237999.804 559184.039, 237997.629 559182.209, 237995.516 559181.057, 237991.369 559179.11, 237981.089 559174.716, 237976.646 559173.527, 237976.478 559173.378, 237975.23 559172.266, 237970.55 559170.985, 237965.023 559169.918, 237957.747 559169.422, 237950.797 559167.528, 237948.688 559166.923, 237947.024 559165.183, 237944.03 559162.379, 237940.46 559158.259, 237928.379 559142.147, 237923.454 559136.261, 237921.587 559133.989, 237919.3 559132.442, 237913.681 559130.358, 237908.639 559129.862, 237901.642 559130.185, 237898.518 559128.692, 237895.341 559127.889, 237892.202 559125.737, 237889.158 559122.641, 237887.389 559120.75, 237887.096 559119.546, 237887.075 559114.575, 237884.804 559103.22, 237883.348 559098.017, 237881.936 559092.557, 237879.398 559086.496, 237875.214 559078.92, 237872.665 559073.999, 237868.583 559068.144, 237870.131 559068.483, 237872.307 559069.333, 237874.395 559070.966, 237876.465 559072.647, 237879.825 559078.702, 237883.479 559084.981, 237886.463 559091.163, 237887.427 559094.974, 237889.667 559110.733, 237889.946 559115.041, 237890.889 559117.373, 237892.722 559119.941, 237894.712 559122.245, 237896.893 559123.641, 237899.319 559125.244, 237908.263 559126.498, 237913.074 559126.468, 237916.189 559126.593, 237920.049 559128.154, 237923.795 559130.434, 237929.918 559135.277, 237937.618 559144.88, 237942.808 559152.25, 237946.273 559156.22, 237948.817 559159.339, 237951.009 559160.849, 237953.633 559162.364, 237958.399 559163.843, 237974.915 559167.071, 237982.599 559170.017, 237987.761 559171.595, 237990.798 559172.618, 237994.341 559174.436, 237997.567 559176.785, 238000.491 559179.071, 238003.459 559182.084, 238006.692 559186.509, 238013.294 559198.082, 238016.046 559202.483, 238020.337 559208.247, 238025.47 559214.232, 238031.171 559219.456, 238037.085 559225.254, 238047.86 559232.568, 238060.705 559241.562, 238070.236 559246.753, 238087.261 559255.797, 238098.419 559263.806, 238108.669 559270.369, 238118.459 559278.389, 238133.523 559291.194, 238138.212 559296.078, 238141.368 559299.164, 238143.738 559302.87, 238144.579 559305.325, 238145.518 559308.363, 238145.592 559311.663, 238144.793 559317.895, 238144.186 559322.238, 238143.054 559326.813, 238142.223 559331.451, 238139.989 559336.468, 238136.747 559342.671, 238134.981 559344.818, 238131.394 559349.253, 238129.518 559351.683, 238127.53 559354.397, 238125.898 559356.759, 238124.529 559360.26, 238124.163 559362.734, 238124.837 559365.615, 238126.131 559368.028, 238128.436 559370.782, 238131.523 559373.623, 238135.581 559376.079, 238142.36 559379.106, 238149.071 559381.89, 238162.919 559387.894, 238171.209 559389.984, 238179.215 559391.964, 238187.507 559393.074, 238202.642 559392.439, 238208.253 559390.921, 238212.902 559389.627, 238218.713 559387.315, 238224.761 559383.841, 238228.404 559381.773, 238234.583 559379.495, 238238.614 559378.67, 238241.405 559378.505, 238244.708 559378.704, 238248.277 559379.061, 238251.498 559379.609, 238254.322 559380.057, 238257.511 559381.246, 238263.292 559384.594, 238267.962 559388.271, 238272.513 559393.373, 238276.671 559398.922, 238278.593 559402.234, 238282.787 559407.689, 238284.833 559409.851, 238293.68 559417.775, 238297.554 559420.978, 238303.318 559423.39, 238310.614 559425.094, 238323.852 559430.15, 238340.734 559435.65, 238357.508 559440.451, 238375.812 559446.777, 238382.21 559449.383, 238384.051 559450.811, 238385.09 559452.198, 238385.565 559454.892, 238385.611 559458.128, 238385.797 559461.417, 238385.418 559466.013, 238383.471 559474.905, 238382.053 559501.559, 238381.509 559505.326, 238381.634 559508.212, 238381.95 559509.916, 238384.44 559512.197, 238391.76 559515.654, 238397.549 559518.84, 238402.201 559520.056, 238408.364 559522.843, 238412.569 559524.92, 238416.781 559527.819, 238419.623 559530.454, 238421.672 559533.163, 238422.545 559534.976, 238422.709 559537.766, 238421.949 559541.668, 238421.097 559544.825, 238418.726 559550.334, 238412.069 559561.368, 238409.509 559566.803, 238408.18 559569.229, 238407.778 559572.071, 238407.287 559574.442, 238407.197 559578.443, 238407.919 559586.085, 238408.718 559592.831, 238409.986 559597.962, 238411.56 559602.447, 238416.72 559610.731, 238419.696 559616.092, 238423.224 559622.976, 238425.532 559626.277, 238430.105 559631.878, 238434.994 559635.89, 238435.924 559640.857, 238437.627 559654.5, 238438.183 559662.568, 238439.449 559668.678, 238439.8 559676.013, 238442.009 559685.709, 238442.408 559691.807, 238443.013 559696.953, 238443.461 559704.596, 238444.325 559709.787, 238445.515 559717.066, 238447.186 559723.18, 238446.218 559724.756, 238444.989 559728.039, 238444.241 559732.328, 238444.309 559740.807, 238443.56 559745.094, 238442.789 559748.882, 238441.255 559752.809, 238440.377 559756.174, 238439.419 559759.181, 238439.272 559762.069, 238439.778 559765.101, 238440.59 559767.49, 238442.422 559770.06, 238444.465 559771.948, 238448.851 559774.26, 238457.559 559777.93, 238466.237 559781.262, 238481.782 559788.094, 238489.439 559792.5, 238492.799 559795.065, 238495.478 559798.674, 238500.558 559808.837, 238507.659 559822.624, 238513.715 559837.964, 238516.66 559845.221, 238520.22 559857.462, 238521.35 559865.318, 238522.036 559869.84, 238521.757 559873.765, 238521.274 559877.231, 238519.991 559880.655, 238517.747 559884.306, 238514.697 559887.367, 238497.762 559896.517, 238489.404 559902.415, 238486.625 559905.202, 238484.904 559907.093, 238484.101 559909.288, 238483.951 559911.628, 238484.606 559914.556, 238486.046 559916.59, 238489.183 559920.704, 238492.219 559922.981, 238494.643 559924.035, 238497.635 559926.567, 238510.812 559938.198, 238515.803 559942.873, 238520.297 559948.116, 238526.92 559956.427, 238535.132 559966.394, 238539.196 559972.178, 238541.731 559976.44, 238543.033 559979.947, 238543.832 559984.458, 238543.625 559987.92, 238542.113 559992.347, 238540.552 559995.228, 238535.19 560000.714, 238530.535 560004.95, 238527.448 560008.107, 238525.598 560010.329, 238523.776 560013.598, 238521.288 560019.825, 238520.026 560023.749, 238519.344 560026.755, 238519.012 560030.115, 238519.522 560033.695, 238523.845 560049.286, 238528.828 560068.353, 238531.38 560087.779, 238532.791 560098.963, 238532.886 560104.999, 238533.76 560108.065, 238536.89 560112.614, 238540.022 560118.416, 238543.552 560124.593, 238553.703 560145.786, 238560.868 560160.523, 238563.901 560166.997, 238565.875 560172.129, 238566.675 560175.386, 238567.113 560178.174, 238566.957 560179.967, 238566.301 560181.784, 238565.242 560183.66, 238563.344 560185.864, 238560.669 560187.545, 238555.879 560190.038, 238552.897 560192.365, 238531.828 560211.677, 238514.566 560228.784, 238510.319 560225.328)))";
        String wktLargeGeography = "MULTIPOLYGON(((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)), ((1 1, 1 2, 2 1, 1 1), (0 0, 0 3, 3 3, 3 0, 0 0 7)), ((9 9, 9 10, 10 9, 9 9)))";
        beforeEachSetup();

        Geometry geomWKT = Geometry.STGeomFromText(wktLargeGeometry, 0);
        Geography geogWKT = Geography.STGeomFromText(wktLargeGeography, 4326);

        try (Connection con = getConnection(); Statement stmt = con.createStatement()) {

            try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                    "insert into " + AbstractSQLGenerator.escapeIdentifier(geomTableName) + " values (?)");) {
                pstmt.setObject(1, geomWKT);
                pstmt.execute();

                pstmt.setGeometry(1, geomWKT);
                pstmt.execute();

                try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                        .executeQuery("select c1 from " + AbstractSQLGenerator.escapeIdentifier(geomTableName))) {
                    rs.next();
                    assertEquals(wktLargeGeometry, rs.getGeometry(1).asTextZM());
                    assertEquals(0, rs.getGeometry(1).getSrid());
                    rs.next();
                    assertEquals(wktLargeGeometry, rs.getGeometry(1).asTextZM());
                    assertEquals(0, rs.getGeometry(1).getSrid());
                }
            }

            try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                    "insert into " + AbstractSQLGenerator.escapeIdentifier(geogTableName) + " values (?)");) {
                pstmt.setObject(1, geogWKT);
                pstmt.execute();

                pstmt.setGeography(1, geogWKT);
                pstmt.execute();

                try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                        .executeQuery("select c1 from " + AbstractSQLGenerator.escapeIdentifier(geogTableName))) {
                    rs.next();
                    assertEquals(wktLargeGeography, rs.getGeography(1).asTextZM());
                    assertEquals(4326, rs.getGeography(1).getSrid());
                    rs.next();
                    assertEquals(wktLargeGeography, rs.getGeography(1).asTextZM());
                    assertEquals(4326, rs.getGeography(1).getSrid());
                }
            }
        }
    }

    /**
     * Tests Geography almost zero coordinates like 0.0001234. The string representation is "1.234E-4", which
     * caused a bug when creating a Geography object.
     */
    @Test
    public void testGeographySmallCoordinates() throws SQLException {
        // Scientific notation with 'e' (lowercase)
        Geography g1 = Geography.point(1.234e-1, 5.678e-1, 4326);
        assertEquals(1.234e-1, g1.getLatitude(), "Latitude should match for scientific notation with lowercase e");
        assertEquals(5.678e-1, g1.getLongitude(), "Longitude should match for scientific notation with lowercase e");

        // Scientific notation with 'E' (uppercase) and positive exponent
        Geography g2 = Geography.point(1.234E+1, 5.678E+1, 4326);
        assertEquals(1.234E+1, g2.getLatitude(), "Latitude should match for scientific notation with uppercase E and positive exponent");
        assertEquals(5.678E+1, g2.getLongitude(), "Longitude should match for scientific notation with uppercase E and positive exponent");

        // Negative scientific notation
        Geography g3 = Geography.point(-1.234e-1, -5.678e-1, 4326);
        assertEquals(-1.234e-1, g3.getLatitude(), "Latitude should match for negative scientific notation");
        assertEquals(-5.678e-1, g3.getLongitude(), "Longitude should match for negative scientific notation");

        // Mix of minus sign and scientific notation
        Geography g4 = Geography.point(-2.5e-1, 3.7e+1, 4326);
        assertEquals(-2.5e-1, g4.getLatitude(), "Latitude should match for negative value with scientific notation");
        assertEquals(3.7e+1, g4.getLongitude(), "Longitude should match for positive scientific notation");

        // All four coordinates (X, Y, Z, M) with scientific notation
        // Note: Geography.STGeomFromText supports Z and M coordinates
        // WKT format: POINT(longitude latitude altitude measure)
        String wktWithAllCoords = "POINT(1.234e-1 5.678e-1 1.5e+1 2.3e+1)";
        Geography g5 = Geography.STGeomFromText(wktWithAllCoords, 4326);
        assertEquals(5.678e-1, g5.getLatitude(), "Latitude (Y) should match for WKT with all 4 coordinates");
        assertEquals(1.234e-1, g5.getLongitude(), "Longitude (X) should match for WKT with all 4 coordinates");
        assertEquals(1.5e+1, g5.getZ(), "Z coordinate should match for WKT with all 4 coordinates");
        assertEquals(2.3e+1, g5.getM(), "M coordinate should match for WKT with all 4 coordinates");
    }

    private void beforeEachSetup() throws SQLException {
        try (Statement stmt = connection.createStatement()) {
            TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(geomTableName), stmt);
            TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(geogTableName), stmt);
            stmt.executeUpdate(
                    "Create table " + AbstractSQLGenerator.escapeIdentifier(geomTableName) + " (c1 geometry)");
            stmt.executeUpdate(
                    "Create table " + AbstractSQLGenerator.escapeIdentifier(geogTableName) + " (c1 geography)");
        }
    }

    private void beforeEachSetupSpatialDatatype() throws SQLException {
        try (Statement stmt = connection.createStatement()) {
            TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(spatialDatatypeTableName), stmt);
            stmt.executeUpdate("Create table " + AbstractSQLGenerator.escapeIdentifier(spatialDatatypeTableName)
                    + " (c1 geometry," + "c2 geography," + "c3 nvarchar(512)," + "c4 decimal(28,4)," + "c5 int)");
        }
    }

    private void testWkt(String geoWKT) throws SQLException {
        testWkt(geoWKT, geoWKT);
    }

    private void testWkt(String geoWKT, String geoWKTSS) throws SQLException {
        Geometry geomWKT = Geometry.STGeomFromText(geoWKT, 0);
        Geography geogWKT = Geography.STGeomFromText(geoWKT, 4326);

        try (Connection con = getConnection(); Statement stmt = con.createStatement()) {

            try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                    "insert into " + AbstractSQLGenerator.escapeIdentifier(geomTableName) + " values (?)");) {
                pstmt.setGeometry(1, geomWKT);
                pstmt.execute();

                try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                        .executeQuery("select c1 from " + AbstractSQLGenerator.escapeIdentifier(geomTableName))) {
                    rs.next();
                    assertEquals(geoWKTSS, rs.getGeometry(1).asTextZM());
                }
            }

            try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) con.prepareStatement(
                    "insert into " + AbstractSQLGenerator.escapeIdentifier(geogTableName) + " values (?)");) {
                pstmt.setGeography(1, geogWKT);
                pstmt.execute();

                try (SQLServerResultSet rs = (SQLServerResultSet) stmt
                        .executeQuery("select c1 from " + AbstractSQLGenerator.escapeIdentifier(geogTableName))) {
                    rs.next();
                    assertEquals(geoWKTSS, rs.getGeography(1).asTextZM());
                }
            }
        }
    }

    private static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
        }

        return data;
    }

    private void validateGeometryGeography(String geoWKT, byte[] geomCLR, byte[] geogCLR,
            byte[] geoWKB) throws SQLServerException {
        Geometry geomWKT = Geometry.deserialize(geomCLR);
        Geography geogWKT = Geography.deserialize(geogCLR);
        assertEquals(geoWKT, geomWKT.asTextZM());
        assertEquals(geoWKT, geogWKT.asTextZM());
        assertArrayEquals(geoWKB, geomWKT.STAsBinary());
        assertArrayEquals(geoWKB, geogWKT.STAsBinary());
    }

    /**
     * Prepare test
     * 
     * @throws SQLException
     * @throws SecurityException
     * @throws IOException
     */
    @BeforeAll
    public static void setupHere() throws Exception {
        setConnection();

        geomTableName = RandomUtil.getIdentifier("geometryTestTable");
        geogTableName = RandomUtil.getIdentifier("geographyTestTable");
        spatialDatatypeTableName = RandomUtil.getIdentifier("spatialDatatypeTestTable");

        try (Connection con = getConnection(); Statement stmt = con.createStatement();
                SQLServerResultSet rs = (SQLServerResultSet) stmt
                        .executeQuery("select SERVERPROPERTY ( 'ProductVersion' )")) {
            rs.next();
            int version = Integer.parseInt(rs.getString(1).substring(0, 2));

            // if major version is greater than or equal to 11, it's SQL Server 2012 or above.
            if (version >= 11) {
                isDenaliOrLater = true;
            }
        }
    }

    /**
     * drop the tables
     * 
     * @throws SQLException
     */
    @AfterAll
    public static void afterAll() throws SQLException {
        try (Statement stmt = connection.createStatement()) {
            TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(geomTableName), stmt);
            TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(geogTableName), stmt);
            TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(spatialDatatypeTableName), stmt);
        }
    }
}
